Annotation of src/usr.bin/file/file.c, Revision 1.54
1.54 ! nicm 1: /* $OpenBSD: file.c,v 1.53 2015/10/17 04:41:37 deraadt Exp $ */
1.27 nicm 2:
1.14 tedu 3: /*
1.27 nicm 4: * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.14 tedu 17: */
1.11 ian 18:
1.20 deraadt 19: #include <sys/types.h>
1.27 nicm 20: #include <sys/ioctl.h>
21: #include <sys/mman.h>
1.35 nicm 22: #include <sys/socket.h>
23: #include <sys/queue.h>
24: #include <sys/uio.h>
25: #include <sys/wait.h>
1.20 deraadt 26:
1.27 nicm 27: #include <errno.h>
1.35 nicm 28: #include <imsg.h>
1.27 nicm 29: #include <libgen.h>
30: #include <getopt.h>
31: #include <fcntl.h>
32: #include <pwd.h>
1.1 deraadt 33: #include <stdlib.h>
1.44 nicm 34: #include <time.h>
1.14 tedu 35: #include <unistd.h>
1.48 deraadt 36: #include <limits.h>
1.14 tedu 37:
1.27 nicm 38: #include "file.h"
39: #include "magic.h"
40: #include "xmalloc.h"
1.1 deraadt 41:
1.35 nicm 42: struct input_msg
43: {
44: int idx;
45:
46: struct stat sb;
47: int error;
48:
49: char link_path[PATH_MAX];
50: int link_error;
51: int link_target;
52: };
53:
54: struct input_ack
55: {
56: int idx;
57: };
58:
1.27 nicm 59: struct input_file
60: {
1.35 nicm 61: struct magic *m;
62: struct input_msg *msg;
1.1 deraadt 63:
1.35 nicm 64: const char *path;
65: int fd;
1.14 tedu 66:
1.35 nicm 67: void *base;
68: size_t size;
69: int mapped;
70: char *result;
1.27 nicm 71: };
1.1 deraadt 72:
1.27 nicm 73: extern char *__progname;
1.1 deraadt 74:
1.27 nicm 75: __dead void usage(void);
1.1 deraadt 76:
1.35 nicm 77: static void send_message(struct imsgbuf *, void *, size_t, int);
78: static int read_message(struct imsgbuf *, struct imsg *, pid_t);
79:
80: static void read_link(struct input_msg *, const char *);
81:
82: static __dead void child(int, pid_t, int, char **);
83:
84: static void test_file(struct input_file *, size_t);
1.27 nicm 85:
86: static int try_stat(struct input_file *);
87: static int try_empty(struct input_file *);
88: static int try_access(struct input_file *);
89: static int try_text(struct input_file *);
90: static int try_magic(struct input_file *);
91: static int try_unknown(struct input_file *);
92:
93: static int bflag;
94: static int cflag;
95: static int iflag;
96: static int Lflag;
97: static int sflag;
98: static int Wflag;
99:
1.35 nicm 100: static char *magicpath;
101: static FILE *magicfp;
102:
1.27 nicm 103: static struct option longopts[] = {
104: { "mime", no_argument, NULL, 'i' },
105: { "mime-type", no_argument, NULL, 'i' },
106: { NULL, 0, NULL, 0 }
107: };
1.14 tedu 108:
1.27 nicm 109: __dead void
110: usage(void)
111: {
1.39 jmc 112: fprintf(stderr, "usage: %s [-bchiLsW] file ...\n", __progname);
1.27 nicm 113: exit(1);
114: }
1.14 tedu 115:
1.1 deraadt 116: int
1.27 nicm 117: main(int argc, char **argv)
1.1 deraadt 118: {
1.54 ! nicm 119: int opt, pair[2], fd, idx, mode, error;
1.35 nicm 120: char *home;
1.27 nicm 121: struct passwd *pw;
1.35 nicm 122: struct imsgbuf ibuf;
123: struct imsg imsg;
124: struct input_msg msg;
125: struct input_ack *ack;
126: pid_t pid, parent;
1.44 nicm 127:
128: tzset();
1.27 nicm 129:
130: for (;;) {
131: opt = getopt_long(argc, argv, "bchiLsW", longopts, NULL);
132: if (opt == -1)
1.18 chl 133: break;
1.27 nicm 134: switch (opt) {
1.9 millert 135: case 'b':
1.27 nicm 136: bflag = 1;
1.9 millert 137: break;
1.1 deraadt 138: case 'c':
1.27 nicm 139: cflag = 1;
1.14 tedu 140: break;
1.27 nicm 141: case 'h':
142: Lflag = 0;
1.14 tedu 143: break;
1.19 chl 144: case 'i':
1.27 nicm 145: iflag = 1;
1.19 chl 146: break;
1.27 nicm 147: case 'L':
148: Lflag = 1;
1.14 tedu 149: break;
150: case 's':
1.27 nicm 151: sflag = 1;
1.14 tedu 152: break;
1.27 nicm 153: case 'W':
154: Wflag = 1;
1.18 chl 155: break;
1.1 deraadt 156: default:
1.27 nicm 157: usage();
1.1 deraadt 158: }
1.27 nicm 159: }
160: argc -= optind;
161: argv += optind;
162: if (cflag) {
163: if (argc != 0)
164: usage();
165: } else if (argc == 0)
166: usage();
1.1 deraadt 167:
1.35 nicm 168: magicfp = NULL;
1.32 nicm 169: if (geteuid() != 0 && !issetugid()) {
170: home = getenv("HOME");
171: if (home == NULL || *home == '\0') {
172: pw = getpwuid(getuid());
173: if (pw != NULL)
174: home = pw->pw_dir;
175: else
176: home = NULL;
177: }
178: if (home != NULL) {
1.35 nicm 179: xasprintf(&magicpath, "%s/.magic", home);
180: magicfp = fopen(magicpath, "r");
181: if (magicfp == NULL)
182: free(magicpath);
1.32 nicm 183: }
1.27 nicm 184: }
1.35 nicm 185: if (magicfp == NULL) {
186: magicpath = xstrdup("/etc/magic");
187: magicfp = fopen(magicpath, "r");
188: }
189: if (magicfp == NULL)
190: err(1, "%s", magicpath);
191:
192: parent = getpid();
193: if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
194: err(1, "socketpair");
1.49 nicm 195: switch (pid = fork()) {
196: case -1:
197: err(1, "fork");
198: case 0:
1.35 nicm 199: close(pair[0]);
200: child(pair[1], parent, argc, argv);
201: }
202: close(pair[1]);
203:
204: fclose(magicfp);
205: magicfp = NULL;
206:
207: if (cflag)
208: goto wait_for_child;
209:
210: imsg_init(&ibuf, pair[0]);
211: for (idx = 0; idx < argc; idx++) {
212: memset(&msg, 0, sizeof msg);
213: msg.idx = idx;
214:
1.45 nicm 215: if (strcmp(argv[idx], "-") == 0) {
216: if (fstat(STDIN_FILENO, &msg.sb) == -1) {
217: fd = -1;
218: msg.error = errno;
219: } else
220: fd = STDIN_FILENO;
1.35 nicm 221: } else {
1.54 ! nicm 222: if (Lflag)
! 223: error = stat(argv[idx], &msg.sb);
! 224: else
! 225: error = lstat(argv[idx], &msg.sb);
! 226: if (error == -1) {
1.49 nicm 227: fd = -1;
1.54 ! nicm 228: msg.error = errno;
! 229: } else {
! 230: /*
! 231: * pledge(2) doesn't let us pass directory file
! 232: * descriptors around - but in fact we don't
! 233: * need them, so just don't open directories or
! 234: * symlinks (which could be to directories).
! 235: */
! 236: mode = msg.sb.st_mode;
! 237: if (!S_ISDIR(mode) && !S_ISLNK(mode)) {
! 238: fd = open(argv[idx],
! 239: O_RDONLY|O_NONBLOCK);
! 240: if (fd == -1 && (errno == ENFILE ||
! 241: errno == EMFILE))
! 242: err(1, "open");
! 243: } else
! 244: fd = -1;
! 245: if (S_ISLNK(mode))
! 246: read_link(&msg, argv[idx]);
! 247: }
1.35 nicm 248: }
249: send_message(&ibuf, &msg, sizeof msg, fd);
1.1 deraadt 250:
1.35 nicm 251: if (read_message(&ibuf, &imsg, pid) == 0)
252: break;
253: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof *ack)
254: errx(1, "message too small");
255: ack = imsg.data;
256: if (ack->idx != idx)
257: errx(1, "index not expected");
258: imsg_free(&imsg);
1.1 deraadt 259: }
260:
1.35 nicm 261: wait_for_child:
262: close(pair[0]);
263: while (wait(NULL) == -1 && errno != ECHILD) {
264: if (errno != EINTR)
265: err(1, "wait");
1.30 nicm 266: }
1.35 nicm 267: _exit(0); /* let the child flush */
1.1 deraadt 268: }
269:
1.27 nicm 270: static void
1.35 nicm 271: send_message(struct imsgbuf *ibuf, void *msg, size_t msglen, int fd)
272: {
273: if (imsg_compose(ibuf, -1, -1, 0, fd, msg, msglen) != 1)
274: err(1, "imsg_compose");
275: if (imsg_flush(ibuf) != 0)
276: err(1, "imsg_flush");
277: }
278:
279: static int
280: read_message(struct imsgbuf *ibuf, struct imsg *imsg, pid_t from)
1.27 nicm 281: {
1.35 nicm 282: int n;
1.1 deraadt 283:
1.35 nicm 284: if ((n = imsg_read(ibuf)) == -1)
285: err(1, "imsg_read");
286: if (n == 0)
287: return (0);
1.27 nicm 288:
1.35 nicm 289: if ((n = imsg_get(ibuf, imsg)) == -1)
290: err(1, "imsg_get");
291: if (n == 0)
292: return (0);
1.31 nicm 293:
1.35 nicm 294: if ((pid_t)imsg->hdr.pid != from)
295: errx(1, "PIDs don't match");
1.27 nicm 296:
1.35 nicm 297: return (n);
1.27 nicm 298:
299: }
300:
301: static void
1.35 nicm 302: read_link(struct input_msg *msg, const char *path)
1.14 tedu 303: {
1.27 nicm 304: struct stat sb;
1.35 nicm 305: char lpath[PATH_MAX];
1.27 nicm 306: char *copy, *root;
307: int used;
308: ssize_t size;
309:
1.47 tobias 310: size = readlink(path, lpath, sizeof lpath - 1);
1.27 nicm 311: if (size == -1) {
1.35 nicm 312: msg->link_error = errno;
1.14 tedu 313: return;
1.27 nicm 314: }
1.35 nicm 315: lpath[size] = '\0';
1.27 nicm 316:
1.35 nicm 317: if (*lpath == '/')
318: strlcpy(msg->link_path, lpath, sizeof msg->link_path);
1.27 nicm 319: else {
1.35 nicm 320: copy = xstrdup(path);
1.27 nicm 321:
322: root = dirname(copy);
323: if (*root == '\0' || strcmp(root, ".") == 0 ||
324: strcmp (root, "/") == 0)
1.35 nicm 325: strlcpy(msg->link_path, lpath, sizeof msg->link_path);
1.27 nicm 326: else {
1.35 nicm 327: used = snprintf(msg->link_path, sizeof msg->link_path,
328: "%s/%s", root, lpath);
329: if (used < 0 || (size_t)used >= sizeof msg->link_path) {
330: msg->link_error = ENAMETOOLONG;
1.37 lteo 331: free(copy);
1.27 nicm 332: return;
333: }
334: }
335:
336: free(copy);
337: }
338:
1.54 ! nicm 339: if (!Lflag && stat(path, &sb) == -1)
! 340: msg->link_target = errno;
1.14 tedu 341: }
342:
1.35 nicm 343: static __dead void
344: child(int fd, pid_t parent, int argc, char **argv)
345: {
1.49 nicm 346: struct passwd *pw;
1.35 nicm 347: struct magic *m;
348: struct imsgbuf ibuf;
349: struct imsg imsg;
350: struct input_msg *msg;
351: struct input_ack ack;
352: struct input_file inf;
353: int i, idx;
354: size_t len, width = 0;
355:
1.53 deraadt 356: if (pledge("stdio getpw recvfd id", NULL) == -1)
1.52 deraadt 357: err(1, "pledge");
1.49 nicm 358:
359: if (geteuid() == 0) {
360: pw = getpwnam(FILE_USER);
361: if (pw == NULL)
362: errx(1, "unknown user %s", FILE_USER);
363: if (setgroups(1, &pw->pw_gid) != 0)
364: err(1, "setgroups");
365: if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0)
366: err(1, "setresgid");
367: if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0)
368: err(1, "setresuid");
369: }
370:
1.52 deraadt 371: if (pledge("stdio recvfd", NULL) == -1)
372: err(1, "pledge");
1.49 nicm 373:
1.35 nicm 374: m = magic_load(magicfp, magicpath, cflag || Wflag);
375: if (cflag) {
376: magic_dump(m);
377: exit(0);
378: }
379:
380: for (i = 0; i < argc; i++) {
381: len = strlen(argv[i]) + 1;
382: if (len > width)
383: width = len;
384: }
385:
386: imsg_init(&ibuf, fd);
387: for (;;) {
388: if (read_message(&ibuf, &imsg, parent) == 0)
389: break;
390: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof *msg)
391: errx(1, "message too small");
392: msg = imsg.data;
393:
394: idx = msg->idx;
395: if (idx < 0 || idx >= argc)
396: errx(1, "index out of range");
397:
398: memset(&inf, 0, sizeof inf);
399: inf.m = m;
400: inf.msg = msg;
401:
402: inf.path = argv[idx];
403: inf.fd = imsg.fd;
404:
405: test_file(&inf, width);
406:
407: if (imsg.fd != -1)
408: close(imsg.fd);
409: imsg_free(&imsg);
410:
411: ack.idx = idx;
412: send_message(&ibuf, &ack, sizeof ack, -1);
413: }
414: exit(0);
415: }
416:
1.27 nicm 417: static void *
1.42 nicm 418: fill_buffer(int fd, size_t size, size_t *used)
1.1 deraadt 419: {
1.27 nicm 420: static void *buffer;
421: ssize_t got;
422: size_t left;
423: void *next;
424:
425: if (buffer == NULL)
426: buffer = xmalloc(FILE_READ_SIZE);
427:
428: next = buffer;
1.42 nicm 429: left = size;
1.27 nicm 430: while (left != 0) {
1.42 nicm 431: got = read(fd, next, left);
1.27 nicm 432: if (got == -1) {
433: if (errno == EINTR)
434: continue;
435: return NULL;
1.5 millert 436: }
1.27 nicm 437: if (got == 0)
438: break;
1.30 nicm 439: next = (char *)next + got;
1.27 nicm 440: left -= got;
441: }
1.42 nicm 442: *used = size - left;
1.27 nicm 443: return buffer;
444: }
445:
446: static int
447: load_file(struct input_file *inf)
448: {
1.42 nicm 449: size_t used;
450:
1.46 tobias 451: if (inf->msg->sb.st_size == 0 && S_ISREG(inf->msg->sb.st_mode))
1.43 nicm 452: return (0); /* empty file */
1.46 tobias 453: if (inf->msg->sb.st_size == 0 || inf->msg->sb.st_size > FILE_READ_SIZE)
1.27 nicm 454: inf->size = FILE_READ_SIZE;
1.46 tobias 455: else
456: inf->size = inf->msg->sb.st_size;
1.43 nicm 457:
458: if (!S_ISREG(inf->msg->sb.st_mode))
459: goto try_read;
1.27 nicm 460:
461: inf->base = mmap(NULL, inf->size, PROT_READ, MAP_PRIVATE, inf->fd, 0);
1.43 nicm 462: if (inf->base == MAP_FAILED)
463: goto try_read;
464: inf->mapped = 1;
465: return (0);
466:
467: try_read:
468: inf->base = fill_buffer(inf->fd, inf->size, &used);
469: if (inf->base == NULL) {
470: xasprintf(&inf->result, "cannot read '%s' (%s)", inf->path,
471: strerror(errno));
472: return (1);
473: }
474: inf->size = used;
1.27 nicm 475: return (0);
476: }
1.5 millert 477:
1.27 nicm 478: static int
479: try_stat(struct input_file *inf)
480: {
1.35 nicm 481: if (inf->msg->error != 0) {
1.27 nicm 482: xasprintf(&inf->result, "cannot stat '%s' (%s)", inf->path,
1.35 nicm 483: strerror(inf->msg->error));
1.27 nicm 484: return (1);
485: }
1.45 nicm 486: if (sflag || strcmp(inf->path, "-") == 0) {
1.35 nicm 487: switch (inf->msg->sb.st_mode & S_IFMT) {
1.45 nicm 488: case S_IFIFO:
489: if (strcmp(inf->path, "-") != 0)
490: break;
1.27 nicm 491: case S_IFBLK:
492: case S_IFCHR:
493: case S_IFREG:
494: return (0);
1.5 millert 495: }
1.27 nicm 496: }
1.1 deraadt 497:
1.35 nicm 498: if (iflag && (inf->msg->sb.st_mode & S_IFMT) != S_IFREG) {
1.27 nicm 499: xasprintf(&inf->result, "application/x-not-regular-file");
500: return (1);
1.1 deraadt 501: }
502:
1.35 nicm 503: switch (inf->msg->sb.st_mode & S_IFMT) {
1.27 nicm 504: case S_IFDIR:
505: xasprintf(&inf->result, "directory");
506: return (1);
507: case S_IFLNK:
1.35 nicm 508: if (inf->msg->link_error != 0) {
1.27 nicm 509: xasprintf(&inf->result, "unreadable symlink '%s' (%s)",
1.35 nicm 510: inf->path, strerror(inf->msg->link_error));
1.27 nicm 511: return (1);
512: }
1.35 nicm 513: if (inf->msg->link_target == ELOOP)
1.27 nicm 514: xasprintf(&inf->result, "symbolic link in a loop");
1.35 nicm 515: else if (inf->msg->link_target != 0) {
1.27 nicm 516: xasprintf(&inf->result, "broken symbolic link to '%s'",
1.35 nicm 517: inf->msg->link_path);
1.27 nicm 518: } else {
519: xasprintf(&inf->result, "symbolic link to '%s'",
1.35 nicm 520: inf->msg->link_path);
1.27 nicm 521: }
522: return (1);
523: case S_IFSOCK:
524: xasprintf(&inf->result, "socket");
525: return (1);
526: case S_IFBLK:
527: xasprintf(&inf->result, "block special (%ld/%ld)",
1.35 nicm 528: (long)major(inf->msg->sb.st_rdev),
529: (long)minor(inf->msg->sb.st_rdev));
1.27 nicm 530: return (1);
531: case S_IFCHR:
532: xasprintf(&inf->result, "character special (%ld/%ld)",
1.35 nicm 533: (long)major(inf->msg->sb.st_rdev),
534: (long)minor(inf->msg->sb.st_rdev));
1.27 nicm 535: return (1);
536: case S_IFIFO:
537: xasprintf(&inf->result, "fifo (named pipe)");
538: return (1);
1.1 deraadt 539: }
1.27 nicm 540: return (0);
541: }
542:
543: static int
544: try_empty(struct input_file *inf)
545: {
546: if (inf->size != 0)
547: return (0);
548:
549: if (iflag)
550: xasprintf(&inf->result, "application/x-empty");
551: else
552: xasprintf(&inf->result, "empty");
553: return (1);
554: }
555:
556: static int
557: try_access(struct input_file *inf)
558: {
559: char tmp[256] = "";
560:
1.49 nicm 561: if (inf->msg->sb.st_size == 0 && S_ISREG(inf->msg->sb.st_mode))
562: return (0); /* empty file */
1.27 nicm 563: if (inf->fd != -1)
564: return (0);
1.1 deraadt 565:
1.35 nicm 566: if (inf->msg->sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
1.27 nicm 567: strlcat(tmp, "writable, ", sizeof tmp);
1.35 nicm 568: if (inf->msg->sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
1.27 nicm 569: strlcat(tmp, "executable, ", sizeof tmp);
1.35 nicm 570: if (S_ISREG(inf->msg->sb.st_mode))
1.27 nicm 571: strlcat(tmp, "regular file, ", sizeof tmp);
572: strlcat(tmp, "no read permission", sizeof tmp);
573:
574: inf->result = xstrdup(tmp);
575: return (1);
1.1 deraadt 576: }
577:
1.27 nicm 578: static int
579: try_text(struct input_file *inf)
1.14 tedu 580: {
1.27 nicm 581: const char *type, *s;
582: int flags;
583:
584: flags = MAGIC_TEST_TEXT;
585: if (iflag)
586: flags |= MAGIC_TEST_MIME;
587:
588: type = text_get_type(inf->base, inf->size);
589: if (type == NULL)
590: return (0);
1.14 tedu 591:
1.27 nicm 592: s = magic_test(inf->m, inf->base, inf->size, flags);
593: if (s != NULL) {
594: inf->result = xstrdup(s);
595: return (1);
596: }
597:
598: s = text_try_words(inf->base, inf->size, flags);
599: if (s != NULL) {
600: if (iflag)
601: inf->result = xstrdup(s);
1.18 chl 602: else
1.27 nicm 603: xasprintf(&inf->result, "%s %s text", type, s);
604: return (1);
1.18 chl 605: }
1.14 tedu 606:
1.27 nicm 607: if (iflag)
608: inf->result = xstrdup("text/plain");
1.14 tedu 609: else
1.27 nicm 610: xasprintf(&inf->result, "%s text", type);
611: return (1);
1.14 tedu 612: }
613:
1.27 nicm 614: static int
615: try_magic(struct input_file *inf)
1.1 deraadt 616: {
1.27 nicm 617: const char *s;
618: int flags;
1.1 deraadt 619:
1.27 nicm 620: flags = 0;
621: if (iflag)
622: flags |= MAGIC_TEST_MIME;
623:
624: s = magic_test(inf->m, inf->base, inf->size, flags);
625: if (s != NULL) {
626: inf->result = xstrdup(s);
627: return (1);
1.1 deraadt 628: }
1.27 nicm 629: return (0);
1.14 tedu 630: }
1.1 deraadt 631:
1.27 nicm 632: static int
633: try_unknown(struct input_file *inf)
1.14 tedu 634: {
1.27 nicm 635: if (iflag)
636: xasprintf(&inf->result, "application/x-not-regular-file");
637: else
638: xasprintf(&inf->result, "data");
639: return (1);
1.1 deraadt 640: }
641:
1.27 nicm 642: static void
1.35 nicm 643: test_file(struct input_file *inf, size_t width)
1.1 deraadt 644: {
1.35 nicm 645: char *label;
646: int stop;
1.27 nicm 647:
648: stop = 0;
649: if (!stop)
650: stop = try_stat(inf);
651: if (!stop)
652: stop = try_access(inf);
653: if (!stop)
654: stop = load_file(inf);
655: if (!stop)
656: stop = try_empty(inf);
657: if (!stop)
658: stop = try_magic(inf);
659: if (!stop)
660: stop = try_text(inf);
661: if (!stop)
662: stop = try_unknown(inf);
663:
664: if (bflag)
665: printf("%s\n", inf->result);
1.35 nicm 666: else {
1.45 nicm 667: if (strcmp(inf->path, "-") == 0)
668: xasprintf(&label, "/dev/stdin:");
669: else
670: xasprintf(&label, "%s:", inf->path);
1.35 nicm 671: printf("%-*s %s\n", (int)width, label, inf->result);
672: free(label);
673: }
1.30 nicm 674: free(inf->result);
1.27 nicm 675:
676: if (inf->mapped && inf->base != NULL)
677: munmap(inf->base, inf->size);
1.1 deraadt 678: }