Annotation of src/usr.bin/kdump/kdump.c, Revision 1.64
1.64 ! guenther 1: /* $OpenBSD: kdump.c,v 1.63 2011/09/19 22:00:37 deraadt Exp $ */
1.4 deraadt 2:
1.1 deraadt 3: /*-
4: * Copyright (c) 1988, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.21 millert 15: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
32: #include <sys/param.h>
33: #include <sys/time.h>
34: #include <sys/uio.h>
35: #include <sys/ktrace.h>
36: #include <sys/ioctl.h>
1.62 otto 37: #include <sys/malloc.h>
38: #include <sys/namei.h>
1.1 deraadt 39: #include <sys/ptrace.h>
1.62 otto 40: #include <sys/sem.h>
41: #include <sys/shm.h>
1.51 otto 42: #include <sys/socket.h>
1.28 deraadt 43: #include <sys/sysctl.h>
1.63 deraadt 44: #include <sys/siginfo.h>
1.55 otto 45: #include <sys/un.h>
1.62 otto 46: #include <sys/vmmeter.h>
1.55 otto 47: #include <sys/stat.h>
1.62 otto 48: #include <sys/tty.h>
1.55 otto 49: #include <netinet/in.h>
50: #include <arpa/inet.h>
1.1 deraadt 51: #define _KERNEL
52: #include <sys/errno.h>
53: #undef _KERNEL
1.62 otto 54: #include <ddb/db_var.h>
55: #include <machine/cpu.h>
1.1 deraadt 56:
1.33 tedu 57: #include <ctype.h>
1.1 deraadt 58: #include <err.h>
1.61 matthew 59: #include <fcntl.h>
1.64 ! guenther 60: #include <limits.h>
1.1 deraadt 61: #include <signal.h>
62: #include <stdio.h>
63: #include <stdlib.h>
1.55 otto 64: #include <stdint.h>
1.1 deraadt 65: #include <string.h>
1.55 otto 66: #include <grp.h>
67: #include <pwd.h>
1.1 deraadt 68: #include <unistd.h>
69: #include <vis.h>
70:
71: #include "ktrace.h"
1.22 deraadt 72: #include "kdump.h"
1.51 otto 73: #include "kdump_subr.h"
1.12 espie 74: #include "extern.h"
1.1 deraadt 75:
1.58 otto 76: int timestamp, decimal, iohex, fancy = 1, tail, maxdata = INT_MAX, resolv;
1.1 deraadt 77: char *tracefile = DEF_TRACEFILE;
78: struct ktr_header ktr_header;
1.17 deraadt 79: pid_t pid = -1;
1.1 deraadt 80:
1.55 otto 81: #define TIME_FORMAT "%b %e %T %Y"
1.1 deraadt 82: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
83:
84: #include <sys/syscall.h>
85:
1.25 mickey 86: #include <compat/linux/linux_syscall.h>
1.1 deraadt 87:
88: #define KTRACE
1.19 mickey 89: #define PTRACE
1.7 deraadt 90: #define NFSCLIENT
91: #define NFSSERVER
92: #define SYSVSEM
93: #define SYSVMSG
94: #define SYSVSHM
95: #define LFS
1.25 mickey 96: #include <kern/syscalls.c>
1.1 deraadt 97:
1.25 mickey 98: #include <compat/linux/linux_syscalls.c>
1.1 deraadt 99: #undef KTRACE
1.19 mickey 100: #undef PTRACE
1.7 deraadt 101: #undef NFSCLIENT
102: #undef NFSSERVER
103: #undef SYSVSEM
104: #undef SYSVMSG
105: #undef SYSVSHM
106: #undef LFS
1.1 deraadt 107:
108: struct emulation {
109: char *name; /* Emulation name */
110: char **sysnames; /* Array of system call names */
111: int nsysnames; /* Number of */
112: };
113:
114: static struct emulation emulations[] = {
1.9 deraadt 115: { "native", syscallnames, SYS_MAXSYSCALL },
116: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
1.49 miod 117: { NULL, NULL, 0 }
1.1 deraadt 118: };
119:
1.59 otto 120: static struct emulation *current;
1.60 otto 121: static struct emulation *def_emul;
1.59 otto 122:
123: struct pid_emul {
124: struct emulation *e;
125: pid_t p;
126: };
127:
128: static struct pid_emul *pe_table;
129: static size_t pe_size;
1.1 deraadt 130:
131:
132: static char *ptrace_ops[] = {
133: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
134: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
1.15 art 135: "PT_KILL", "PT_ATTACH", "PT_DETACH", "PT_IO",
1.64 ! guenther 136: "PT_SET_EVENT_MASK", "PT_GET_EVENT_MASK", "PT_GET_PROCESS_STATE",
1.1 deraadt 137: };
138:
1.52 otto 139: static int narg;
140: static register_t *ap;
141: static char sep;
142:
1.59 otto 143: static void mappidtoemul(pid_t, struct emulation *);
144: static struct emulation * findemul(pid_t);
1.37 tedu 145: static int fread_tail(void *, size_t, size_t);
1.13 millert 146: static void dumpheader(struct ktr_header *);
147: static void ktrcsw(struct ktr_csw *);
1.37 tedu 148: static void ktremul(char *, size_t);
149: static void ktrgenio(struct ktr_genio *, size_t);
150: static void ktrnamei(const char *, size_t);
1.13 millert 151: static void ktrpsig(struct ktr_psig *);
152: static void ktrsyscall(struct ktr_syscall *);
1.62 otto 153: static const char *kresolvsysctl(int, int *, int);
1.13 millert 154: static void ktrsysret(struct ktr_sysret *);
1.55 otto 155: static void ktrstruct(char *, size_t);
1.13 millert 156: static void setemul(const char *);
157: static void usage(void);
1.61 matthew 158: static void atfd(int);
1.12 espie 159:
1.1 deraadt 160: int
1.17 deraadt 161: main(int argc, char *argv[])
1.1 deraadt 162: {
1.37 tedu 163: int ch, silent;
164: size_t ktrlen, size;
1.17 deraadt 165: int trpoints = ALL_POINTS;
1.12 espie 166: void *m;
1.1 deraadt 167:
1.60 otto 168: def_emul = current = &emulations[0]; /* native */
1.1 deraadt 169:
1.55 otto 170: while ((ch = getopt(argc, argv, "e:f:dlm:nrRp:Tt:xX")) != -1)
1.1 deraadt 171: switch (ch) {
172: case 'e':
173: setemul(optarg);
1.60 otto 174: def_emul = current;
1.1 deraadt 175: break;
176: case 'f':
177: tracefile = optarg;
178: break;
179: case 'd':
180: decimal = 1;
181: break;
182: case 'l':
183: tail = 1;
184: break;
185: case 'm':
186: maxdata = atoi(optarg);
187: break;
188: case 'n':
189: fancy = 0;
190: break;
1.17 deraadt 191: case 'p':
192: pid = atoi(optarg);
193: break;
1.55 otto 194: case 'r':
195: resolv = 1;
196: break;
1.1 deraadt 197: case 'R':
198: timestamp = 2; /* relative timestamp */
199: break;
200: case 'T':
201: timestamp = 1;
202: break;
203: case 't':
204: trpoints = getpoints(optarg);
205: if (trpoints < 0)
206: errx(1, "unknown trace point in %s", optarg);
207: break;
1.31 tedu 208: case 'x':
209: iohex = 1;
210: break;
211: case 'X':
212: iohex = 2;
213: break;
1.1 deraadt 214: default:
215: usage();
216: }
1.5 deraadt 217: if (argc > optind)
1.1 deraadt 218: usage();
219:
1.37 tedu 220: m = malloc(size = 1025);
1.1 deraadt 221: if (m == NULL)
1.37 tedu 222: err(1, NULL);
1.1 deraadt 223: if (!freopen(tracefile, "r", stdin))
224: err(1, "%s", tracefile);
225: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
1.17 deraadt 226: silent = 0;
1.59 otto 227: if (pe_size == 0)
228: mappidtoemul(ktr_header.ktr_pid, current);
1.17 deraadt 229: if (pid != -1 && pid != ktr_header.ktr_pid)
230: silent = 1;
231: if (silent == 0 && trpoints & (1<<ktr_header.ktr_type))
1.1 deraadt 232: dumpheader(&ktr_header);
1.37 tedu 233: ktrlen = ktr_header.ktr_len;
1.1 deraadt 234: if (ktrlen > size) {
1.23 tedu 235: void *newm;
236:
1.64 ! guenther 237: if (ktrlen == SIZE_MAX)
! 238: errx(1, "data too long");
1.23 tedu 239: newm = realloc(m, ktrlen+1);
240: if (newm == NULL)
1.37 tedu 241: err(1, NULL);
1.23 tedu 242: m = newm;
1.1 deraadt 243: size = ktrlen;
244: }
245: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
246: errx(1, "data too short");
1.17 deraadt 247: if (silent)
248: continue;
1.1 deraadt 249: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
250: continue;
1.59 otto 251: current = findemul(ktr_header.ktr_pid);
1.1 deraadt 252: switch (ktr_header.ktr_type) {
253: case KTR_SYSCALL:
254: ktrsyscall((struct ktr_syscall *)m);
255: break;
256: case KTR_SYSRET:
257: ktrsysret((struct ktr_sysret *)m);
258: break;
259: case KTR_NAMEI:
260: ktrnamei(m, ktrlen);
261: break;
262: case KTR_GENIO:
263: ktrgenio((struct ktr_genio *)m, ktrlen);
264: break;
265: case KTR_PSIG:
266: ktrpsig((struct ktr_psig *)m);
267: break;
268: case KTR_CSW:
269: ktrcsw((struct ktr_csw *)m);
270: break;
271: case KTR_EMUL:
272: ktremul(m, ktrlen);
1.59 otto 273: mappidtoemul(ktr_header.ktr_pid, current);
1.1 deraadt 274: break;
1.55 otto 275: case KTR_STRUCT:
276: ktrstruct(m, ktrlen);
277: break;
1.1 deraadt 278: }
279: if (tail)
280: (void)fflush(stdout);
281: }
1.12 espie 282: exit(0);
1.1 deraadt 283: }
284:
1.59 otto 285: static void
286: mappidtoemul(pid_t pid, struct emulation *emul)
287: {
288: size_t i;
289: struct pid_emul *tmp;
290:
291: for (i = 0; i < pe_size; i++) {
292: if (pe_table[i].p == pid) {
293: pe_table[i].e = emul;
294: return;
295: }
296: }
297: tmp = realloc(pe_table, (pe_size + 1) * sizeof(*pe_table));
298: if (tmp == NULL)
299: err(1, NULL);
300: pe_table = tmp;
301: pe_table[pe_size].p = pid;
302: pe_table[pe_size].e = emul;
303: pe_size++;
304: }
305:
306: static struct emulation*
307: findemul(pid_t pid)
308: {
309: size_t i;
310:
311: for (i = 0; i < pe_size; i++)
312: if (pe_table[i].p == pid)
313: return pe_table[i].e;
1.60 otto 314: return def_emul;
1.59 otto 315: }
316:
1.12 espie 317: static int
1.37 tedu 318: fread_tail(void *buf, size_t size, size_t num)
1.1 deraadt 319: {
320: int i;
321:
322: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
323: (void)sleep(1);
324: clearerr(stdin);
325: }
326: return (i);
327: }
328:
1.12 espie 329: static void
1.17 deraadt 330: dumpheader(struct ktr_header *kth)
1.1 deraadt 331: {
1.17 deraadt 332: static struct timeval prevtime;
1.1 deraadt 333: char unknown[64], *type;
334: struct timeval temp;
335:
336: switch (kth->ktr_type) {
337: case KTR_SYSCALL:
338: type = "CALL";
339: break;
340: case KTR_SYSRET:
341: type = "RET ";
342: break;
343: case KTR_NAMEI:
344: type = "NAMI";
345: break;
346: case KTR_GENIO:
347: type = "GIO ";
348: break;
349: case KTR_PSIG:
350: type = "PSIG";
351: break;
352: case KTR_CSW:
353: type = "CSW";
354: break;
355: case KTR_EMUL:
356: type = "EMUL";
357: break;
1.55 otto 358: case KTR_STRUCT:
359: type = "STRU";
360: break;
1.1 deraadt 361: default:
1.17 deraadt 362: (void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)",
363: kth->ktr_type);
1.1 deraadt 364: type = unknown;
365: }
366:
1.16 mpech 367: (void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN,
368: kth->ktr_comm);
1.1 deraadt 369: if (timestamp) {
370: if (timestamp == 2) {
371: timersub(&kth->ktr_time, &prevtime, &temp);
372: prevtime = kth->ktr_time;
373: } else
374: temp = kth->ktr_time;
375: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
376: }
377: (void)printf("%s ", type);
378: }
379:
1.12 espie 380: static void
1.17 deraadt 381: ioctldecode(u_long cmd)
1.2 deraadt 382: {
383: char dirbuf[4], *dir = dirbuf;
384:
1.6 deraadt 385: if (cmd & IOC_IN)
386: *dir++ = 'W';
1.2 deraadt 387: if (cmd & IOC_OUT)
388: *dir++ = 'R';
389: *dir = '\0';
390:
1.33 tedu 391: printf(decimal ? ",_IO%s('%c',%lu" : ",_IO%s('%c',%#lx",
392: dirbuf, (int)((cmd >> 8) & 0xff), cmd & 0xff);
1.2 deraadt 393: if ((cmd & IOC_VOID) == 0)
1.34 tedu 394: printf(decimal ? ",%lu)" : ",%#lx)", (cmd >> 16) & 0xff);
1.2 deraadt 395: else
396: printf(")");
397: }
1.1 deraadt 398:
1.52 otto 399: static void
400: ptracedecode(void)
401: {
402: if (*ap >= 0 && *ap <
403: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
404: (void)printf("%s", ptrace_ops[*ap]);
405: else switch(*ap) {
406: #ifdef PT_GETFPREGS
407: case PT_GETFPREGS:
408: (void)printf("PT_GETFPREGS");
409: break;
410: #endif
411: case PT_GETREGS:
412: (void)printf("PT_GETREGS");
413: break;
414: #ifdef PT_SETFPREGS
415: case PT_SETFPREGS:
416: (void)printf("PT_SETFPREGS");
417: break;
418: #endif
419: case PT_SETREGS:
420: (void)printf("PT_SETREGS");
421: break;
422: #ifdef PT_STEP
423: case PT_STEP:
424: (void)printf("PT_STEP");
425: break;
426: #endif
427: #ifdef PT_WCOOKIE
428: case PT_WCOOKIE:
429: (void)printf("PT_WCOOKIE");
430: break;
431: #endif
432: default:
433: (void)printf("%ld", (long)*ap);
434: break;
435: }
436: sep = ',';
437: ap++;
438: narg--;
439: }
440:
441: static void
442: pn(void (*f)(int))
443: {
444: if (sep)
445: (void)putchar(sep);
446: if (fancy && f != NULL)
447: f((int)*ap);
448: else if (decimal)
449: (void)printf("%ld", (long)*ap);
450: else
451: (void)printf("%#lx", (long)*ap);
452: ap++;
453: narg--;
454: sep = ',';
455: }
456:
457: #ifdef __LP64__
458: #define plln() pn(NULL)
459: #elif _BYTE_ORDER == _LITTLE_ENDIAN
460: static void
461: plln(void)
462: {
463: long long val = ((long long)*ap) & 0xffffffff;
464: ap++;
465: val |= ((long long)*ap) << 32;
466: ap++;
467: narg -= 2;
468: if (sep)
469: (void)putchar(sep);
470: if (decimal)
471: (void)printf("%lld", val);
472: else
473: (void)printf("%#llx", val);
474: sep = ',';
475: }
476: #else
477: static void
478: plln(void)
479: {
480: long long val = ((long long)*ap) << 32;
481: ap++;
482: val |= ((long long)*ap) & 0xffffffff;
483: ap++;
484: narg -= 2;
485: if (sep)
486: (void)putchar(sep);
487: if (decimal)
488: (void)printf("%lld", val);
489: else
490: (void)printf("%#llx", val);
491: sep = ',';
492: }
493: #endif
1.51 otto 494:
1.12 espie 495: static void
1.17 deraadt 496: ktrsyscall(struct ktr_syscall *ktr)
1.1 deraadt 497: {
1.52 otto 498: narg = ktr->ktr_argsize / sizeof(register_t);
499: sep = '\0';
1.1 deraadt 500:
501: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
502: (void)printf("[%d]", ktr->ktr_code);
503: else
504: (void)printf("%s", current->sysnames[ktr->ktr_code]);
505: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
1.27 mickey 506: (void)putchar('(');
1.52 otto 507:
1.54 otto 508: if (current != &emulations[0])
509: goto nonnative;
510:
1.52 otto 511: switch (ktr->ktr_code) {
512: case SYS_ioctl: {
513: const char *cp;
514:
515: pn(NULL);
516: if (!fancy)
517: break;
518: if ((cp = ioctlname(*ap)) != NULL)
519: (void)printf(",%s", cp);
520: else
521: ioctldecode(*ap);
522: ap++;
523: narg--;
524: break;
525: }
526: case SYS___sysctl: {
1.62 otto 527: const char *s;
528: int *np, n, i, *top;
1.52 otto 529:
530: if (!fancy)
531: break;
532: n = ap[1];
533: if (n > CTL_MAXNAME)
534: n = CTL_MAXNAME;
1.62 otto 535: np = top = (int *)(ap + 6);
536: for (i = 0; n--; np++, i++) {
1.52 otto 537: if (sep)
538: putchar(sep);
1.62 otto 539: if (resolv && (s = kresolvsysctl(i, top, *np)) != NULL)
540: printf("%s", s);
541: else
542: printf("%d", *np);
1.52 otto 543: sep = '.';
1.1 deraadt 544: }
1.52 otto 545:
546: sep = ',';
547: ap += 2;
548: narg -= 2;
549: break;
550: }
551: case SYS_ptrace:
552: if (!fancy)
553: break;
554: ptracedecode();
555: break;
556: case SYS_access:
557: pn(NULL);
558: pn(accessmodename);
559: break;
560: case SYS_chmod:
561: case SYS_fchmod:
1.61 matthew 562: pn(NULL);
1.52 otto 563: pn(modename);
564: break;
565: case SYS_fcntl: {
566: int cmd;
567: int arg;
568: pn(NULL);
569: if (!fancy)
570: break;
571: cmd = ap[0];
572: arg = ap[1];
573: (void)putchar(',');
574: fcntlcmdname(cmd, arg);
575: ap += 2;
576: narg -= 2;
577: break;
578: }
579: case SYS_flock:
580: pn(NULL);
581: pn(flockname);
582: break;
583: case SYS_getrlimit:
584: case SYS_setrlimit:
585: pn(rlimitname);
586: break;
587: case SYS_getsockopt:
588: case SYS_setsockopt: {
589: int level;
590:
591: pn(NULL);
592: level = *ap;
593: pn(sockoptlevelname);
594: if (level == SOL_SOCKET)
595: pn(sockoptname);
596: break;
597: }
598: case SYS_kill:
599: pn(NULL);
600: pn(signame);
601: break;
602: case SYS_lseek:
603: pn(NULL);
604: /* skip padding */
605: ap++;
606: narg--;
607: plln();
608: pn(whencename);
609: break;
610: case SYS_madvise:
611: pn(NULL);
612: pn(NULL);
613: pn(madvisebehavname);
614: break;
615: case SYS_minherit:
616: pn(NULL);
617: pn(NULL);
618: pn(minheritname);
619: break;
620: case SYS_mlockall:
621: pn(mlockallname);
622: break;
623: case SYS_mmap:
624: pn(NULL);
625: pn(NULL);
626: pn(mmapprotname);
627: pn(mmapflagsname);
628: pn(NULL);
629: /* skip padding */
630: ap++;
631: narg--;
632: plln();
633: break;
634: case SYS_mprotect:
635: pn(NULL);
636: pn(NULL);
637: pn(mmapprotname);
638: break;
639: case SYS_mquery:
640: pn(NULL);
641: pn(NULL);
642: pn(mmapprotname);
643: pn(mmapflagsname);
644: pn(NULL);
645: /* skip padding */
646: ap++;
647: narg--;
648: plln();
649: break;
650: case SYS_msync:
651: pn(NULL);
652: pn(NULL);
653: pn(msyncflagsname);
654: break;
655: case SYS_msgctl:
656: pn(NULL);
657: pn(shmctlname);
658: break;
659: case SYS_open: {
660: int flags;
661: int mode;
662:
663: pn(NULL);
664: if (!fancy)
665: break;
666: flags = ap[0];
667: mode = ap[1];
668: (void)putchar(',');
669: flagsandmodename(flags, mode);
670: ap += 2;
671: narg -= 2;
672: break;
673: }
674: case SYS_pread:
675: case SYS_preadv:
676: case SYS_pwrite:
677: case SYS_pwritev:
678: pn(NULL);
679: pn(NULL);
680: pn(NULL);
681: /* skip padding */
682: ap++;
683: narg--;
684: plln();
685: break;
686: case SYS_recvmsg:
687: case SYS_sendmsg:
688: pn(NULL);
689: pn(NULL);
690: pn(sendrecvflagsname);
691: break;
692: case SYS_recvfrom:
693: case SYS_sendto:
694: pn(NULL);
695: pn(NULL);
696: pn(NULL);
697: pn(sendrecvflagsname);
698: break;
699: case SYS___semctl:
700: pn(NULL);
701: pn(NULL);
702: pn(semctlname);
703: break;
704: case SYS_semget:
705: pn(NULL);
706: pn(NULL);
707: pn(semgetname);
708: break;
709: case SYS_shmat:
710: pn(NULL);
711: pn(NULL);
712: pn(shmatname);
713: break;
714: case SYS_shmctl:
715: pn(NULL);
716: pn(shmctlname);
717: break;
1.64 ! guenther 718: case SYS_clock_gettime:
! 719: case SYS_clock_settime:
! 720: case SYS_clock_getres:
! 721: pn(clockname);
! 722: break;
1.52 otto 723: case SYS_sigaction:
724: pn(signame);
725: break;
726: case SYS_sigprocmask:
727: pn(sigprocmaskhowname);
1.64 ! guenther 728: pn(sigset);
! 729: break;
! 730: case SYS_sigsuspend:
! 731: pn(sigset);
1.52 otto 732: break;
733: case SYS_socket: {
734: int sockdomain = *ap;
735:
736: pn(sockdomainname);
737: pn(socktypename);
738: if (sockdomain == PF_INET || sockdomain == PF_INET6)
739: pn(sockipprotoname);
740: break;
741: }
742: case SYS_socketpair:
743: pn(sockdomainname);
744: pn(socktypename);
745: break;
746: case SYS_truncate:
747: case SYS_ftruncate:
748: pn(NULL);
749: /* skip padding */
750: ap++;
751: narg--;
752: plln();
753: break;
754: case SYS_wait4:
755: pn(NULL);
756: pn(NULL);
757: pn(wait4optname);
758: break;
1.64 ! guenther 759: case SYS___thrsleep:
! 760: pn(NULL);
! 761: pn(clockname);
! 762: break;
! 763: case SYS___thrsigdivert:
! 764: pn(sigset);
! 765: break;
1.61 matthew 766: case SYS_faccessat:
767: pn(atfd);
768: pn(NULL);
769: pn(accessmodename);
770: pn(atflagsname);
771: break;
772: case SYS_fchmodat:
773: pn(atfd);
774: pn(NULL);
775: pn(modename);
776: pn(atflagsname);
777: break;
778: case SYS_fchownat:
779: pn(atfd);
780: pn(NULL);
781: pn(NULL);
782: pn(NULL);
783: pn(atflagsname);
784: break;
785: case SYS_fstatat:
786: pn(atfd);
787: pn(NULL);
788: pn(NULL);
789: pn(atflagsname);
790: break;
791: case SYS_linkat:
792: pn(atfd);
793: pn(NULL);
794: pn(atfd);
795: pn(NULL);
796: pn(atflagsname);
797: break;
798: case SYS_mkdirat:
799: case SYS_mkfifoat:
800: case SYS_mknodat:
801: pn(atfd);
802: pn(NULL);
803: pn(modename);
804: break;
805: case SYS_openat: {
806: int flags;
807: int mode;
808:
809: pn(atfd);
810: pn(NULL);
811: if (!fancy)
812: break;
813: flags = ap[0];
814: mode = ap[1];
815: (void)putchar(',');
816: flagsandmodename(flags, mode);
817: ap += 2;
818: narg -= 2;
819: break;
820: }
821: case SYS_readlinkat:
822: pn(atfd);
823: break;
824: case SYS_renameat:
825: pn(atfd);
826: pn(NULL);
827: pn(atfd);
828: break;
829: case SYS_symlinkat:
830: pn(NULL);
831: pn(atfd);
832: break;
833: case SYS_unlinkat:
834: pn(atfd);
835: pn(NULL);
836: pn(atflagsname);
837: break;
838: case SYS_utimensat:
839: pn(atfd);
840: pn(NULL);
841: pn(NULL);
842: pn(atflagsname);
843: break;
1.52 otto 844: }
845:
1.54 otto 846: nonnative:
1.52 otto 847: while (narg) {
848: if (sep)
849: putchar(sep);
850: if (decimal)
851: (void)printf("%ld", (long)*ap);
852: else
853: (void)printf("%#lx", (long)*ap);
854: sep = ',';
855: ap++;
856: narg--;
1.1 deraadt 857: }
1.27 mickey 858: (void)printf(")\n");
1.62 otto 859: }
860:
861: static struct ctlname topname[] = CTL_NAMES;
862: static struct ctlname kernname[] = CTL_KERN_NAMES;
863: static struct ctlname vmname[] = CTL_VM_NAMES;
864: static struct ctlname fsname[] = CTL_FS_NAMES;
865: static struct ctlname netname[] = CTL_NET_NAMES;
866: static struct ctlname hwname[] = CTL_HW_NAMES;
867: static struct ctlname username[] = CTL_USER_NAMES;
868: static struct ctlname debugname[CTL_DEBUG_MAXID];
869: static struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
870: static struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
871: static struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
1.64 ! guenther 872: static struct ctlname kernprocname[] =
! 873: {
! 874: { NULL },
! 875: { "all" },
! 876: { "pid" },
! 877: { "pgrp" },
! 878: { "session" },
! 879: { "tty" },
! 880: { "uid" },
! 881: { "ruid" },
! 882: };
1.62 otto 883: static struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
884: static struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
885: static struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
886: static struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
887: static struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
888: #ifdef CTL_MACHDEP_NAMES
889: static struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
890: #endif
891: static struct ctlname ddbname[] = CTL_DDB_NAMES;
892:
893: #ifndef nitems
894: #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
895: #endif
896:
897: #define SETNAME(name) do { names = (name); limit = nitems(name); } while (0)
898:
899: static const char *
900: kresolvsysctl(int depth, int *top, int idx)
901: {
902: struct ctlname *names;
903: size_t limit;
904:
905: names = NULL;
906:
907: switch (depth) {
908: case 0:
909: SETNAME(topname);
910: break;
911: case 1:
912: switch (top[0]) {
913: case CTL_KERN:
914: SETNAME(kernname);
915: break;
916: case CTL_VM:
917: SETNAME(vmname);
918: break;
919: case CTL_FS:
920: SETNAME(fsname);
921: break;
922: case CTL_NET:
923: SETNAME(netname);
924: break;
925: case CTL_DEBUG:
926: SETNAME(debugname);
927: break;
928: case CTL_HW:
929: SETNAME(hwname);
930: break;
931: #ifdef CTL_MACHDEP_NAMES
932: case CTL_MACHDEP:
933: SETNAME(machdepname);
934: break;
935: #endif
936: case CTL_USER:
937: SETNAME(username);
938: break;
939: case CTL_DDB:
940: SETNAME(ddbname);
941: break;
942: }
943: break;
944: case 2:
945: switch (top[0]) {
946: case CTL_KERN:
947: switch (top[1]) {
948: case KERN_MALLOCSTATS:
949: SETNAME(kernmallocname);
950: break;
951: case KERN_FORKSTAT:
952: SETNAME(forkstatname);
953: break;
954: case KERN_NCHSTATS:
955: SETNAME(nchstatsname);
956: break;
957: case KERN_TTY:
958: SETNAME(ttysname);
959: break;
960: case KERN_SEMINFO:
961: SETNAME(semname);
962: break;
963: case KERN_SHMINFO:
964: SETNAME(shmname);
965: break;
966: case KERN_WATCHDOG:
967: SETNAME(watchdogname);
968: break;
1.64 ! guenther 969: case KERN_PROC:
! 970: idx++; /* zero is valid at this level */
! 971: SETNAME(kernprocname);
! 972: break;
1.62 otto 973: case KERN_TIMECOUNTER:
974: SETNAME(tcname);
975: break;
976: }
977: }
978: break;
979: }
980: if (names != NULL && idx > 0 && idx < limit)
981: return (names[idx].ctl_name);
982: return (NULL);
1.1 deraadt 983: }
984:
1.12 espie 985: static void
1.17 deraadt 986: ktrsysret(struct ktr_sysret *ktr)
1.1 deraadt 987: {
1.50 deraadt 988: register_t ret = ktr->ktr_retval;
1.12 espie 989: int error = ktr->ktr_error;
990: int code = ktr->ktr_code;
1.1 deraadt 991:
992: if (code >= current->nsysnames || code < 0)
993: (void)printf("[%d] ", code);
1.59 otto 994: else {
1.1 deraadt 995: (void)printf("%s ", current->sysnames[code]);
1.59 otto 996: if (ret > 0 && (strcmp(current->sysnames[code], "fork") == 0 ||
997: strcmp(current->sysnames[code], "vfork") == 0 ||
998: strcmp(current->sysnames[code], "rfork") == 0 ||
1.64 ! guenther 999: strcmp(current->sysnames[code], "__tfork") == 0 ||
1.59 otto 1000: strcmp(current->sysnames[code], "clone") == 0))
1001: mappidtoemul(ret, current);
1002: }
1.1 deraadt 1003:
1004: if (error == 0) {
1005: if (fancy) {
1.64 ! guenther 1006: switch (current == &emulations[0] ? code : -1) {
! 1007: case SYS_sigprocmask:
! 1008: sigset(ret);
! 1009: break;
! 1010: case SYS___thrsigdivert:
! 1011: signame(ret);
! 1012: break;
! 1013: case -1: /* non-default emulation */
! 1014: default:
! 1015: (void)printf("%ld", (long)ret);
! 1016: if (ret < 0 || ret > 9)
! 1017: (void)printf("/%#lx", (long)ret);
! 1018: }
1.1 deraadt 1019: } else {
1020: if (decimal)
1.50 deraadt 1021: (void)printf("%ld", (long)ret);
1.1 deraadt 1022: else
1.50 deraadt 1023: (void)printf("%#lx", (long)ret);
1.1 deraadt 1024: }
1025: } else if (error == ERESTART)
1026: (void)printf("RESTART");
1027: else if (error == EJUSTRETURN)
1028: (void)printf("JUSTRETURN");
1029: else {
1030: (void)printf("-1 errno %d", ktr->ktr_error);
1031: if (fancy)
1032: (void)printf(" %s", strerror(ktr->ktr_error));
1033: }
1034: (void)putchar('\n');
1035: }
1036:
1.12 espie 1037: static void
1.37 tedu 1038: ktrnamei(const char *cp, size_t len)
1.1 deraadt 1039: {
1.37 tedu 1040: (void)printf("\"%.*s\"\n", (int)len, cp);
1.1 deraadt 1041: }
1042:
1.12 espie 1043: static void
1.37 tedu 1044: ktremul(char *cp, size_t len)
1.1 deraadt 1045: {
1046: char name[1024];
1047:
1048: if (len >= sizeof(name))
1049: errx(1, "Emulation name too long");
1050:
1051: strncpy(name, cp, len);
1052: name[len] = '\0';
1053: (void)printf("\"%s\"\n", name);
1054:
1055: setemul(name);
1056: }
1057:
1.12 espie 1058: static void
1.37 tedu 1059: ktrgenio(struct ktr_genio *ktr, size_t len)
1.1 deraadt 1060: {
1.37 tedu 1061: unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio);
1062: int i, j;
1063: size_t datalen = len - sizeof(struct ktr_genio);
1.12 espie 1064: static int screenwidth = 0;
1.31 tedu 1065: int col = 0, width, bpl;
1.32 tedu 1066: unsigned char visbuf[5], *cp, c;
1.1 deraadt 1067:
1068: if (screenwidth == 0) {
1069: struct winsize ws;
1070:
1071: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
1072: ws.ws_col > 8)
1073: screenwidth = ws.ws_col;
1074: else
1075: screenwidth = 80;
1076: }
1.37 tedu 1077: printf("fd %d %s %zu bytes\n", ktr->ktr_fd,
1.1 deraadt 1078: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
1.58 otto 1079: if (maxdata == 0)
1080: return;
1081: if (datalen > maxdata)
1.1 deraadt 1082: datalen = maxdata;
1.31 tedu 1083: if (iohex && !datalen)
1084: return;
1085: if (iohex == 1) {
1086: putchar('\t');
1087: col = 8;
1088: for (i = 0; i < datalen; i++) {
1.35 tedu 1089: printf("%02x", dp[i]);
1.31 tedu 1090: col += 3;
1091: if (i < datalen - 1) {
1092: if (col + 3 > screenwidth) {
1093: printf("\n\t");
1094: col = 8;
1095: } else
1096: putchar(' ');
1097: }
1098: }
1099: putchar('\n');
1100: return;
1101: }
1102: if (iohex == 2) {
1103: bpl = (screenwidth - 13)/4;
1104: if (bpl <= 0)
1105: bpl = 1;
1106: for (i = 0; i < datalen; i += bpl) {
1107: printf(" %04x: ", i);
1108: for (j = 0; j < bpl; j++) {
1109: if (i+j >= datalen)
1110: printf(" ");
1111: else
1.35 tedu 1112: printf("%02x ", dp[i+j]);
1.31 tedu 1113: }
1114: putchar(' ');
1115: for (j = 0; j < bpl; j++) {
1116: if (i+j >= datalen)
1117: break;
1118: c = dp[i+j];
1119: if (!isprint(c))
1120: c = '.';
1121: putchar(c);
1122: }
1123: putchar('\n');
1124: }
1125: return;
1126: }
1.1 deraadt 1127: (void)printf(" \"");
1128: col = 8;
1129: for (; datalen > 0; datalen--, dp++) {
1.31 tedu 1130: (void)vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
1.1 deraadt 1131: cp = visbuf;
1.17 deraadt 1132:
1.1 deraadt 1133: /*
1134: * Keep track of printables and
1135: * space chars (like fold(1)).
1136: */
1137: if (col == 0) {
1138: (void)putchar('\t');
1139: col = 8;
1140: }
1.17 deraadt 1141: switch (*cp) {
1.1 deraadt 1142: case '\n':
1143: col = 0;
1144: (void)putchar('\n');
1145: continue;
1146: case '\t':
1147: width = 8 - (col&07);
1148: break;
1149: default:
1150: width = strlen(cp);
1151: }
1152: if (col + width > (screenwidth-2)) {
1153: (void)printf("\\\n\t");
1154: col = 8;
1155: }
1156: col += width;
1157: do {
1158: (void)putchar(*cp++);
1159: } while (*cp);
1160: }
1161: if (col == 0)
1162: (void)printf(" ");
1163: (void)printf("\"\n");
1164: }
1165:
1.12 espie 1166: static void
1.17 deraadt 1167: ktrpsig(struct ktr_psig *psig)
1.1 deraadt 1168: {
1169: (void)printf("SIG%s ", sys_signame[psig->signo]);
1170: if (psig->action == SIG_DFL)
1.63 deraadt 1171: (void)printf("SIG_DFL");
1.64 ! guenther 1172: else {
! 1173: (void)printf("caught handler=0x%lx mask=",
! 1174: (u_long)psig->action);
! 1175: sigset(psig->mask);
! 1176: }
1.63 deraadt 1177: if (psig->code) {
1178: printf(" code ");
1179: if (fancy) {
1180: switch (psig->signo) {
1181: case SIGILL:
1182: sigill_name(psig->code);
1183: break;
1184: case SIGTRAP:
1185: sigtrap_name(psig->code);
1186: break;
1187: case SIGEMT:
1188: sigemt_name(psig->code);
1189: break;
1190: case SIGFPE:
1191: sigfpe_name(psig->code);
1192: break;
1193: case SIGBUS:
1194: sigbus_name(psig->code);
1195: break;
1196: case SIGSEGV:
1197: sigsegv_name(psig->code);
1198: break;
1199: case SIGCHLD:
1200: sigchld_name(psig->code);
1201: break;
1202: }
1203: }
1204: printf("<%d>", psig->code);
1205: }
1206:
1.14 deraadt 1207: switch (psig->signo) {
1208: case SIGSEGV:
1209: case SIGILL:
1210: case SIGBUS:
1211: case SIGFPE:
1212: printf(" addr=%p trapno=%d", psig->si.si_addr,
1213: psig->si.si_trapno);
1214: break;
1215: default:
1216: break;
1217: }
1218: printf("\n");
1.1 deraadt 1219: }
1220:
1.12 espie 1221: static void
1.17 deraadt 1222: ktrcsw(struct ktr_csw *cs)
1.1 deraadt 1223: {
1224: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
1225: cs->user ? "user" : "kernel");
1226: }
1227:
1.55 otto 1228:
1229:
1.64 ! guenther 1230: static void
1.55 otto 1231: ktrsockaddr(struct sockaddr *sa)
1232: {
1233: /*
1234: TODO: Support additional address families
1235: #include <netnatm/natm.h>
1236: struct sockaddr_natm *natm;
1237: #include <netsmb/netbios.h>
1238: struct sockaddr_nb *nb;
1239: */
1240: char addr[64];
1241:
1242: /*
1243: * note: ktrstruct() has already verified that sa points to a
1244: * buffer at least sizeof(struct sockaddr) bytes long and exactly
1245: * sa->sa_len bytes long.
1246: */
1247: printf("struct sockaddr { ");
1248: sockfamilyname(sa->sa_family);
1249: printf(", ");
1250:
1251: #define check_sockaddr_len(n) \
1252: if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \
1253: printf("invalid"); \
1254: break; \
1255: }
1256:
1257: switch(sa->sa_family) {
1258: case AF_INET: {
1259: struct sockaddr_in *sa_in;
1260:
1261: sa_in = (struct sockaddr_in *)sa;
1262: check_sockaddr_len(in);
1263: inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
1264: printf("%s:%u", addr, ntohs(sa_in->sin_port));
1265: break;
1266: }
1267: case AF_INET6: {
1268: struct sockaddr_in6 *sa_in6;
1269:
1270: sa_in6 = (struct sockaddr_in6 *)sa;
1271: check_sockaddr_len(in6);
1272: inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
1273: printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
1274: break;
1275: }
1276: #ifdef IPX
1277: case AF_IPX: {
1278: struct sockaddr_ipx *sa_ipx;
1279:
1280: sa_ipx = (struct sockaddr_ipx *)sa;
1281: check_sockaddr_len(ipx);
1282: /* XXX wish we had ipx_ntop */
1283: printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
1284: break;
1285: }
1286: #endif
1287: case AF_UNIX: {
1288: struct sockaddr_un *sa_un;
1289:
1290: sa_un = (struct sockaddr_un *)sa;
1291: if (sa_un->sun_len <= sizeof(sa_un->sun_len) +
1292: sizeof(sa_un->sun_family)) {
1293: printf("invalid");
1294: break;
1295: }
1296: printf("\"%.*s\"", (int)(sa_un->sun_len -
1297: sizeof(sa_un->sun_len) - sizeof(sa_un->sun_family)),
1298: sa_un->sun_path);
1299: break;
1300: }
1301: default:
1302: printf("unknown address family");
1303: }
1304: printf(" }\n");
1305: }
1306:
1.64 ! guenther 1307: static void
! 1308: print_time(time_t t, int relative)
! 1309: {
! 1310: char timestr[PATH_MAX + 4];
! 1311: struct tm *tm;
! 1312:
! 1313: if (resolv == 0 || relative)
! 1314: printf("%jd", (intmax_t)t);
! 1315: else {
! 1316: tm = localtime(&t);
! 1317: (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
! 1318: printf("\"%s\"", timestr);
! 1319: }
! 1320: }
! 1321:
! 1322: static void
! 1323: print_timespec(const struct timespec *tsp, int relative)
1.55 otto 1324: {
1.64 ! guenther 1325: print_time(tsp->tv_sec, relative);
! 1326: if (tsp->tv_nsec != 0)
! 1327: printf(".%09ld", tsp->tv_nsec);
! 1328: }
! 1329:
! 1330: static void
! 1331: ktrstat(const struct stat *statp)
! 1332: {
! 1333: char mode[12];
1.55 otto 1334: struct passwd *pwd;
1335: struct group *grp;
1336:
1337: /*
1338: * note: ktrstruct() has already verified that statp points to a
1339: * buffer exactly sizeof(struct stat) bytes long.
1340: */
1.64 ! guenther 1341: printf("struct stat { ");
1.55 otto 1342: strmode(statp->st_mode, mode);
1343: printf("dev=%d, ino=%u, mode=%s, nlink=%u, ",
1344: statp->st_dev, statp->st_ino, mode, statp->st_nlink);
1345: if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
1346: printf("uid=%u, ", statp->st_uid);
1347: else
1348: printf("uid=\"%s\", ", pwd->pw_name);
1349: if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
1350: printf("gid=%u, ", statp->st_gid);
1351: else
1352: printf("gid=\"%s\", ", grp->gr_name);
1353: printf("rdev=%d, ", statp->st_rdev);
1354: printf("atime=");
1.64 ! guenther 1355: print_timespec(&statp->st_atim, 0);
! 1356: printf(", mtime=");
! 1357: print_timespec(&statp->st_mtim, 0);
! 1358: printf(", ctime=");
! 1359: print_timespec(&statp->st_ctim, 0);
! 1360: printf(", size=%lld, blocks=%lld, blksize=%u, flags=0x%x, gen=0x%x",
1.55 otto 1361: statp->st_size, statp->st_blocks, statp->st_blksize,
1362: statp->st_flags, statp->st_gen);
1363: printf(" }\n");
1364: }
1365:
1.64 ! guenther 1366: static void
1.55 otto 1367: ktrstruct(char *buf, size_t buflen)
1368: {
1369: char *name, *data;
1370: size_t namelen, datalen;
1371: int i;
1372:
1373: for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0';
1374: ++namelen)
1375: /* nothing */;
1376: if (namelen == buflen)
1377: goto invalid;
1378: if (name[namelen] != '\0')
1379: goto invalid;
1380: data = buf + namelen + 1;
1381: datalen = buflen - namelen - 1;
1382: if (datalen == 0)
1383: goto invalid;
1384: /* sanity check */
1385: for (i = 0; i < namelen; ++i)
1386: if (!isalpha((unsigned char)name[i]))
1387: goto invalid;
1388: if (strcmp(name, "stat") == 0) {
1.64 ! guenther 1389: struct stat sb;
! 1390:
1.55 otto 1391: if (datalen != sizeof(struct stat))
1392: goto invalid;
1393: memcpy(&sb, data, datalen);
1394: ktrstat(&sb);
1395: } else if (strcmp(name, "sockaddr") == 0) {
1.64 ! guenther 1396: struct sockaddr_storage ss;
! 1397:
1.55 otto 1398: if (datalen > sizeof(ss))
1399: goto invalid;
1400: memcpy(&ss, data, datalen);
1401: if ((ss.ss_family != AF_UNIX &&
1402: datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len)
1403: goto invalid;
1404: ktrsockaddr((struct sockaddr *)&ss);
1405: } else {
1.57 otto 1406: printf("unknown structure %s\n", name);
1.55 otto 1407: }
1408: return;
1409: invalid:
1410: printf("invalid record\n");
1411: }
1412:
1.12 espie 1413: static void
1.17 deraadt 1414: usage(void)
1.1 deraadt 1415: {
1416:
1.19 mickey 1417: extern char *__progname;
1418: fprintf(stderr, "usage: %s "
1.55 otto 1419: "[-dlnRrTXx] [-e emulation] [-f file] [-m maxdata] [-p pid]\n"
1.40 sobrado 1420: "%*s[-t [ceinsw]]\n",
1.51 otto 1421: __progname, (int)(sizeof("usage: ") + strlen(__progname)), "");
1.1 deraadt 1422: exit(1);
1423: }
1424:
1.12 espie 1425: static void
1.17 deraadt 1426: setemul(const char *name)
1.1 deraadt 1427: {
1428: int i;
1.17 deraadt 1429:
1.1 deraadt 1430: for (i = 0; emulations[i].name != NULL; i++)
1431: if (strcmp(emulations[i].name, name) == 0) {
1432: current = &emulations[i];
1433: return;
1434: }
1435: warnx("Emulation `%s' unknown", name);
1.61 matthew 1436: }
1437:
1438: static void
1439: atfd(int fd)
1440: {
1441: if (fd == AT_FDCWD)
1442: (void)printf("AT_FDCWD");
1443: else if (decimal)
1444: (void)printf("%d", fd);
1445: else
1446: (void)printf("%#x", fd);
1.1 deraadt 1447: }