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