/[gentoo-projects]/pax-utils/scanmacho.c
Gentoo

Contents of /pax-utils/scanmacho.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations) (download) (as text)
Tue Dec 30 13:27:09 2008 UTC (5 years, 8 months ago) by vapier
Branch: MAIN
Changes since 1.11: +18 -41 lines
File MIME type: text/x-csrc
cleanup code style a bit and simplify a bunch of places -- hopefully i didnt break anything

1 /*
2 * Copyright 2008 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanmacho.c,v 1.11 2008/12/30 13:13:15 vapier Exp $
5 *
6 * based on scanelf by:
7 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org>
8 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org>
9 * for Darwin specific fun:
10 * 2008 Fabian Groffen - <grobian@gentoo.org>
11 */
12
13 static const char *rcsid = "$Id: scanmacho.c,v 1.11 2008/12/30 13:13:15 vapier Exp $";
14 const char * const argv0 = "scanmacho";
15
16 #include "paxinc.h"
17
18 #define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
19
20 /* prototypes */
21 static int scanmacho_fatobj(fatobj *fobj);
22 static int scanmacho_file(const char *filename, const struct stat *st_cache);
23 static int scanmacho_from_file(const char *filename);
24 static int scanmacho_dir(const char *path);
25 static void scanmacho_envpath(void);
26 static void usage(int status);
27 static int parseargs(int argc, char *argv[]);
28
29 /* variables to control behavior */
30 static char match_etypes[126] = "";
31 static char scan_envpath = 0;
32 static char scan_symlink = 1;
33 static char scan_archives = 0;
34 static char dir_recurse = 0;
35 static char dir_crossmount = 1;
36 static char show_perms = 0;
37 static char show_size = 0;
38 static char show_needed = 0;
39 static char show_interp = 0;
40 static char show_bind = 0;
41 static char show_soname = 0;
42 static char show_banner = 1;
43 static char show_endian = 0;
44 static char be_quiet = 0;
45 static char be_verbose = 0;
46 static char be_wewy_wewy_quiet = 0;
47 static char be_semi_verbose = 0;
48 static char *find_lib = NULL;
49 static char *out_format = NULL;
50 static char *search_path = NULL;
51 static char g_match = 0;
52
53 static int match_bits = 0;
54 static unsigned int match_perms = 0;
55
56 static const char *getstr_perms(const char *fname)
57 {
58 struct stat st;
59 static char buf[8];
60
61 if (stat(fname, &st) == -1)
62 return "";
63
64 snprintf(buf, sizeof(buf), "%o", st.st_mode);
65
66 return buf + 2;
67 }
68
69 static const char *macho_file_needed_lib(
70 fatobj *fobj,
71 char *found_needed,
72 char *found_lib,
73 int op,
74 char **ret,
75 size_t *ret_len
76 ) {
77 loadcmd *lcmd;
78 uint32_t lc_load_dylib;
79
80 if ((op == 0 && !show_needed) || (op == 1 && !find_lib))
81 return NULL;
82
83 lcmd = firstloadcmd(fobj);
84 lc_load_dylib = MGET(fobj->swapped, LC_LOAD_DYLIB);
85
86 do {
87 if (lcmd->lcmd->cmd == lc_load_dylib) {
88 struct dylib_command *dlcmd = (struct dylib_command*)lcmd->data;
89 char *needed;
90 needed = (char *)(lcmd->data + MGET(fobj->swapped, dlcmd->dylib.name.offset));
91 if (op == 0) {
92 if (!be_wewy_wewy_quiet) {
93 if (*found_needed)
94 xchrcat(ret, ',', ret_len);
95 xstrcat(ret, needed, ret_len);
96 }
97 *found_needed = 1;
98 } else {
99 if (!strncmp(find_lib, needed,
100 strlen(!g_match ? needed : find_lib)))
101 {
102 *found_lib = 1;
103 free(lcmd);
104 return (be_wewy_wewy_quiet ? NULL : needed);
105 }
106 }
107 }
108 } while (nextloadcmd(lcmd));
109
110 if (op == 0 && !*found_needed && be_verbose)
111 warn("Mach-O lacks LC_LOAD_DYLIB commands: %s", fobj->filename);
112
113 return NULL;
114 }
115
116 static char *macho_file_interp(fatobj *fobj, char *found_interp)
117 {
118 loadcmd *lcmd;
119 uint32_t lc_load_dylinker;
120
121 if (!show_interp)
122 return NULL;
123
124 lcmd = firstloadcmd(fobj);
125 lc_load_dylinker = MGET(fobj->swapped, LC_LOAD_DYLINKER);
126
127 do {
128 if (lcmd->lcmd->cmd == lc_load_dylinker) {
129 struct dylinker_command *dlcmd =
130 (struct dylinker_command*)lcmd->data;
131 char *dylinker;
132 dylinker = (char *)(lcmd->data + MGET(fobj->swapped, dlcmd->name.offset));
133 *found_interp = 1;
134 free(lcmd);
135 return (be_wewy_wewy_quiet ? NULL : dylinker);
136 }
137 } while (nextloadcmd(lcmd));
138
139 return NULL;
140 }
141
142 static char *macho_file_soname(fatobj *fobj, char *found_soname)
143 {
144 loadcmd *lcmd;
145 uint32_t lc_id_dylib;
146
147 if (!show_soname)
148 return NULL;
149
150 lcmd = firstloadcmd(fobj);
151 lc_id_dylib = MGET(fobj->swapped, LC_ID_DYLIB);
152
153 do {
154 if (lcmd->lcmd->cmd == lc_id_dylib) {
155 struct dylib_command *dlcmd = (struct dylib_command*)lcmd->data;
156 char *soname;
157 soname = (char *)(lcmd->data + MGET(fobj->swapped, dlcmd->dylib.name.offset));
158 *found_soname = 1;
159 free(lcmd);
160 return (be_wewy_wewy_quiet ? NULL : soname);
161 }
162 } while (nextloadcmd(lcmd));
163
164 return NULL;
165 }
166
167 /* scan a macho file and show all the fun stuff */
168 #define prints(str) write(fileno(stdout), str, strlen(str))
169 static int scanmacho_fatobj(fatobj *fobj)
170 {
171 unsigned long i;
172 char found_needed, found_interp, found_soname, found_lib, found_file;
173 static char *out_buffer = NULL;
174 static size_t out_len;
175
176 found_needed = found_interp = found_soname = \
177 found_lib = found_file = 0;
178
179 if (be_verbose > 2)
180 printf("%s: scanning file {%s,%s}\n", fobj->filename,
181 get_machocputype(fobj),
182 get_machosubcputype(fobj));
183 else if (be_verbose > 1)
184 printf("%s: scanning file\n", fobj->filename);
185
186 /* init output buffer */
187 if (!out_buffer) {
188 out_len = sizeof(char) * 80;
189 out_buffer = xmalloc(out_len);
190 }
191 *out_buffer = '\0';
192
193 /* show the header */
194 if (!be_quiet && show_banner) {
195 for (i = 0; out_format[i]; ++i) {
196 if (!IS_MODIFIER(out_format[i])) continue;
197
198 switch (out_format[++i]) {
199 case '+': break;
200 case '%': break;
201 case '#': break;
202 case 'F':
203 case 'p':
204 case 'f': prints("FILE "); found_file = 1; break;
205 case 'o': prints(" TYPE "); break;
206 case 'M': prints("CPU "); break;
207 case 'n': prints("NEEDED "); break;
208 case 'i': prints("DYLINKER "); break;
209 case 'b': prints("FLAGS "); break;
210 case 'Z': prints("SIZE "); break;
211 case 'S': prints("INSTALLNAME "); break;
212 case 'N': prints("LIB "); break;
213 case 'a': prints("ARCH "); break;
214 case 'O': prints("PERM "); break;
215 case 'D': prints("ENDIAN "); break;
216 default: warnf("'%c' has no title ?", out_format[i]);
217 }
218 }
219 if (!found_file) prints("FILE ");
220 prints("\n");
221 found_file = 0;
222 show_banner = 0;
223 }
224
225 /* dump all the good stuff */
226 for (i = 0; out_format[i]; ++i) {
227 const char *out;
228 const char *tmp;
229 static char ubuf[sizeof(unsigned long)*2];
230 if (!IS_MODIFIER(out_format[i])) {
231 xchrcat(&out_buffer, out_format[i], &out_len);
232 continue;
233 }
234
235 out = NULL;
236 be_wewy_wewy_quiet = (out_format[i] == '#');
237 be_semi_verbose = (out_format[i] == '+');
238 switch (out_format[++i]) {
239 case '+':
240 case '%':
241 case '#':
242 xchrcat(&out_buffer, out_format[i], &out_len); break;
243 case 'F':
244 found_file = 1;
245 if (be_wewy_wewy_quiet) break;
246 xstrcat(&out_buffer, fobj->filename, &out_len);
247 break;
248 case 'p':
249 found_file = 1;
250 if (be_wewy_wewy_quiet) break;
251 tmp = fobj->filename;
252 if (search_path) {
253 ssize_t len_search = strlen(search_path);
254 ssize_t len_file = strlen(fobj->filename);
255 if (!strncmp(fobj->filename, search_path, len_search) && \
256 len_file > len_search)
257 tmp += len_search;
258 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++;
259 }
260 xstrcat(&out_buffer, tmp, &out_len);
261 break;
262 case 'f':
263 found_file = 1;
264 if (be_wewy_wewy_quiet) break;
265 xstrcat(&out_buffer, fobj->base_filename, &out_len);
266 break;
267 case 'o': out = get_machomhtype(fobj); break;
268 case 'M': out = get_machocputype(fobj); break;
269 case 'D': out = get_machoendian(fobj); break;
270 case 'O': out = getstr_perms(fobj->filename); break;
271 case 'n':
272 case 'N': out = macho_file_needed_lib(fobj, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break;
273 case 'i': out = macho_file_interp(fobj, &found_interp); break;
274 case 'b': get_machomhflags(fobj, &out_buffer, &out_len); break;
275 case 'S': out = macho_file_soname(fobj, &found_soname); break;
276 case 'a': out = get_machomtype(fobj); break;
277 case 'Z': snprintf(ubuf, sizeof(ubuf), "%llu", (unsigned long long int)fobj->len); out = ubuf; break;;
278 default: warnf("'%c' has no scan code?", out_format[i]);
279 }
280 if (out) {
281 /* hack for comma delimited output like `scanelf -s sym1,sym2,sym3` */
282 if (out_format[i] == 's' && (tmp=strchr(out,',')) != NULL)
283 xstrncat(&out_buffer, out, &out_len, (tmp-out));
284 else
285 xstrcat(&out_buffer, out, &out_len);
286 }
287 }
288
289 #define FOUND_SOMETHING() \
290 ( found_needed || found_interp || found_soname || found_lib )
291
292 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
293 xchrcat(&out_buffer, ' ', &out_len);
294 xstrcat(&out_buffer, fobj->filename, &out_len);
295 }
296 if (!be_quiet || (be_quiet && FOUND_SOMETHING())) {
297 puts(out_buffer);
298 fflush(stdout);
299 }
300
301 return 0;
302 }
303
304 /* scan a single Mach-O */
305 static int scanmacho_fat(const char *filename, int fd, size_t len)
306 {
307 int ret = 1;
308 fatobj *fobj;
309 fatobj *walk;
310
311 /* verify this is real Mach-O */
312 if ((fobj = readmacho_fd(filename, fd, len)) == NULL) {
313 if (be_verbose > 2) printf("%s: not a Mach-O object\n", filename);
314 return ret;
315 }
316 switch (match_bits) {
317 case 32:
318 case 64:
319 walk = fobj;
320 do {
321 if ((walk->ismach64 && match_bits == 64) ||
322 (!walk->ismach64 && match_bits == 32))
323 {
324 ret = scanmacho_fatobj(walk);
325 }
326 } while (walk->next != NULL && (walk = walk->next));
327 goto label_done;
328 default:
329 break;
330 }
331 if (strlen(match_etypes)) {
332 char sbuf[128];
333 char ftype[32];
334
335 snprintf(sbuf, 128, ",%s,", match_etypes);
336
337 walk = fobj;
338 do {
339 snprintf(ftype, 32, ",%s,", get_machomhtype(walk));
340 if (strstr(sbuf, ftype) != NULL) {
341 ret = scanmacho_fatobj(walk);
342 }
343 } while (walk->next != NULL && (walk = walk->next));
344 goto label_done;
345 }
346
347 walk = fobj;
348 do {
349 ret = scanmacho_fatobj(walk);
350 } while (walk->next != NULL && (walk = walk->next));
351
352 label_done:
353 unreadmacho(fobj);
354 return ret;
355 }
356
357 /* scan an archive of Mach-Os */
358 static int scanmacho_archive(const char *filename, int fd, size_t len)
359 {
360 archive_handle *ar;
361 archive_member *m;
362 char *ar_buffer;
363 fatobj *fobj;
364 fatobj *walk;
365
366 ar = ar_open_fd(filename, fd);
367 if (ar == NULL)
368 return 1;
369
370 ar_buffer = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
371 while ((m = ar_next(ar)) != NULL) {
372 fobj = readmacho_buffer(m->name, ar_buffer + lseek(fd, 0, SEEK_CUR), m->size);
373 if (fobj) {
374 walk = fobj;
375 do {
376 scanmacho_fatobj(walk);
377 } while (walk->next != NULL && (walk = walk->next));
378 fobj->data = NULL;
379 unreadmacho(fobj);
380 }
381 }
382 munmap(ar_buffer, len);
383
384 return 0;
385 }
386 /* scan a file which may be an Mach-O or an archive or some other
387 * magical beast */
388 static int scanmacho_file(const char *filename, const struct stat *st_cache)
389 {
390 const struct stat *st = st_cache;
391 struct stat symlink_st;
392 int fd;
393
394 /* always handle regular files and handle symlinked files if no -y */
395 if (S_ISLNK(st->st_mode)) {
396 if (!scan_symlink)
397 return 1;
398 stat(filename, &symlink_st);
399 st = &symlink_st;
400 }
401
402 if (!S_ISREG(st->st_mode)) {
403 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
404 return 1;
405 }
406
407 if (match_perms) {
408 if ((st->st_mode | match_perms) != st->st_mode)
409 return 1;
410 }
411 if ((fd = open(filename, O_RDONLY)) == -1)
412 return 1;
413
414 if (scanmacho_fat(filename, fd, st->st_size) == 1 && scan_archives)
415 /* if it isn't an Mach-O, maybe it's an .a archive */
416 scanmacho_archive(filename, fd, st->st_size);
417
418 close(fd);
419 return 0;
420 }
421
422 /* scan a directory for Mach-O files and print when we find one */
423 static int scanmacho_dir(const char *path)
424 {
425 register DIR *dir;
426 register struct dirent *dentry;
427 struct stat st_top, st;
428 char buf[__PAX_UTILS_PATH_MAX];
429 size_t pathlen = 0, len = 0;
430 int ret = 0;
431
432 /* make sure path exists */
433 if (lstat(path, &st_top) == -1) {
434 if (be_verbose > 2) printf("%s: does not exist\n", path);
435 return 1;
436 }
437
438 /* ok, if it isn't a directory, assume we can open it */
439 if (!S_ISDIR(st_top.st_mode))
440 return scanmacho_file(path, &st_top);
441
442 /* now scan the dir looking for fun stuff */
443 if ((dir = opendir(path)) == NULL) {
444 warnf("could not opendir %s: %s", path, strerror(errno));
445 return 1;
446 }
447 if (be_verbose > 1) printf("%s: scanning dir\n", path);
448
449 pathlen = strlen(path);
450 while ((dentry = readdir(dir))) {
451 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
452 continue;
453 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
454 if (len >= sizeof(buf)) {
455 warnf("Skipping '%s': len > sizeof(buf); %lu > %lu\n", path,
456 (unsigned long)len, (unsigned long)sizeof(buf));
457 continue;
458 }
459 snprintf(buf, sizeof(buf), "%s%s%s", path, (path[pathlen-1] == '/') ? "" : "/", dentry->d_name);
460 if (lstat(buf, &st) != -1) {
461 if (S_ISREG(st.st_mode))
462 ret = scanmacho_file(buf, &st);
463 else if (dir_recurse && S_ISDIR(st.st_mode)) {
464 if (dir_crossmount || (st_top.st_dev == st.st_dev))
465 ret = scanmacho_dir(buf);
466 }
467 }
468 }
469 closedir(dir);
470 return ret;
471 }
472
473 static int scanmacho_from_file(const char *filename)
474 {
475 FILE *fp = NULL;
476 char *p;
477 char path[__PAX_UTILS_PATH_MAX];
478 int ret = 0;
479
480 if (strcmp(filename, "-") == 0)
481 fp = stdin;
482 else if ((fp = fopen(filename, "r")) == NULL)
483 return 1;
484
485 while ((fgets(path, __PAX_UTILS_PATH_MAX, fp)) != NULL) {
486 if ((p = strchr(path, '\n')) != NULL)
487 *p = 0;
488 search_path = path;
489 ret = scanmacho_dir(path);
490 }
491 if (fp != stdin)
492 fclose(fp);
493 return ret;
494 }
495
496 /* scan env PATH for paths */
497 static void scanmacho_envpath(void)
498 {
499 char *path, *p;
500
501 path = getenv("PATH");
502 if (!path)
503 err("PATH is not set in your env !");
504 path = xstrdup(path);
505
506 while ((p = strrchr(path, ':')) != NULL) {
507 scanmacho_dir(p + 1);
508 *p = 0;
509 }
510
511 free(path);
512 }
513
514 /* usage / invocation handling functions */ /* Free Flags: c d e j k l r s t u w x z C G H I J K L P Q T U W X Y */
515 #define PARSE_FLAGS "pRmyAnibSN:gE:M:DO:ZaqvF:f:o:BhV"
516 #define a_argument required_argument
517 static struct option const long_opts[] = {
518 {"path", no_argument, NULL, 'p'},
519 {"recursive", no_argument, NULL, 'R'},
520 {"mount", no_argument, NULL, 'm'},
521 {"symlink", no_argument, NULL, 'y'},
522 {"archives", no_argument, NULL, 'A'},
523 {"needed", no_argument, NULL, 'n'},
524 {"interp", no_argument, NULL, 'i'},
525 {"bind", no_argument, NULL, 'b'},
526 {"soname", no_argument, NULL, 'S'},
527 {"lib", a_argument, NULL, 'N'},
528 {"gmatch", no_argument, NULL, 'g'},
529 {"etype", a_argument, NULL, 'E'},
530 {"bits", a_argument, NULL, 'M'},
531 {"endian", no_argument, NULL, 'D'},
532 {"perms", a_argument, NULL, 'O'},
533 {"size", no_argument, NULL, 'Z'},
534 {"all", no_argument, NULL, 'a'},
535 {"quiet", no_argument, NULL, 'q'},
536 {"verbose", no_argument, NULL, 'v'},
537 {"format", a_argument, NULL, 'F'},
538 {"from", a_argument, NULL, 'f'},
539 {"file", a_argument, NULL, 'o'},
540 {"nobanner", no_argument, NULL, 'B'},
541 {"help", no_argument, NULL, 'h'},
542 {"version", no_argument, NULL, 'V'},
543 {NULL, no_argument, NULL, 0x0}
544 };
545
546 static const char *opts_help[] = {
547 "Scan all directories in PATH environment",
548 "Scan directories recursively",
549 "Don't recursively cross mount points",
550 "Don't scan symlinks",
551 "Scan archives (.a files)",
552 "Print LC_LOAD_DYLIB information (ELF: NEEDED)",
553 "Print LC_LOAD_DYLINKER information (ELF: INTERP)",
554 "Print flags from mach_header (ELF: BIND)",
555 "Print LC_ID_DYLIB information (ELF: SONAME)",
556 "Find a specified library",
557 "Use strncmp to match libraries. (use with -N)",
558 "Print only Mach-O files matching mach_header\n"
559 " MH_OBJECT,MH_EXECUTE ... (ELF: etype)",
560 "Print only Mach-O files matching numeric bits",
561 "Print Endianness",
562 "Print only Mach-O files matching octal permissions",
563 "Print Mach-O file size",
564 "Print all scanned info (-F\"%o %O %D %b %F\")\n",
565 "Only output 'bad' things",
566 "Be verbose (can be specified more than once)",
567 "Use specified format for output",
568 "Read input stream from a filename",
569 "Write output stream to a filename",
570 "Don't display the header",
571 "Print this help and exit",
572 "Print version and exit",
573 NULL
574 };
575
576 /* display usage and exit */
577 static void usage(int status)
578 {
579 unsigned long i;
580 printf("* Scan Mach-O binaries for stuff\n\n"
581 "Usage: %s [options] <dir1/file1> [dir2 dirN file2 fileN ...]\n\n", argv0);
582 printf("Options: -[%s]\n", PARSE_FLAGS);
583 for (i = 0; long_opts[i].name; ++i)
584 if (long_opts[i].has_arg == no_argument)
585 printf(" -%c, --%-14s* %s\n", long_opts[i].val,
586 long_opts[i].name, opts_help[i]);
587 else
588 printf(" -%c, --%-7s <arg> * %s\n", long_opts[i].val,
589 long_opts[i].name, opts_help[i]);
590
591 puts("\nFor more information, see the scanmacho(1) manpage");
592 exit(status);
593 }
594
595 /* parse command line arguments and preform needed actions */
596 static int parseargs(int argc, char *argv[])
597 {
598 int i;
599 const char *from_file = NULL;
600 int ret = 0;
601
602 opterr = 0;
603 while ((i = getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
604 switch (i) {
605
606 case 'V':
607 printf("pax-utils-%s: %s compiled %s\n%s\n"
608 "%s written for Gentoo by <solar, vapier and grobian @ gentoo.org>\n",
609 VERSION, __FILE__, __DATE__, rcsid, argv0);
610 exit(EXIT_SUCCESS);
611 break;
612 case 'h': usage(EXIT_SUCCESS); break;
613 case 'f':
614 if (from_file) warn("You prob don't want to specify -f twice");
615 from_file = optarg;
616 break;
617 case 'E':
618 strncpy(match_etypes, optarg, sizeof(match_etypes));
619 break;
620 case 'M':
621 match_bits = atoi(optarg);
622 break;
623 case 'O':
624 if (sscanf(optarg, "%o", &match_perms) == -1)
625 match_bits = 0;
626 break;
627 case 'o': {
628 if (freopen(optarg, "w", stdout) == NULL)
629 err("Could not open output stream '%s': %s", optarg, strerror(errno));
630 break;
631 }
632 case 'N': {
633 if (find_lib) warn("You prob don't want to specify -N twice");
634 find_lib = optarg;
635 break;
636 }
637 case 'F': {
638 if (out_format) warn("You prob don't want to specify -F twice");
639 out_format = optarg;
640 break;
641 }
642 case 'Z': show_size = 1; break;
643 case 'g': g_match = 1; break;
644 case 'y': scan_symlink = 0; break;
645 case 'A': scan_archives = 1; break;
646 case 'B': show_banner = 0; break;
647 case 'p': scan_envpath = 1; break;
648 case 'R': dir_recurse = 1; break;
649 case 'm': dir_crossmount = 0; break;
650 case 'n': show_needed = 1; break;
651 case 'i': show_interp = 1; break;
652 case 'b': show_bind = 1; break;
653 case 'S': show_soname = 1; break;
654 case 'q': be_quiet = 1; break;
655 case 'v': be_verbose = (be_verbose % 20) + 1; break;
656 case 'a': show_perms = show_endian = show_bind = 1; break;
657 case 'D': show_endian = 1; break;
658 case ':':
659 err("Option '%c' is missing parameter", optopt);
660 case '?':
661 err("Unknown option '%c' or argument missing", optopt);
662 default:
663 err("Unhandled option '%c'; please report this", i);
664 }
665 }
666 /* let the format option override all other options */
667 if (out_format) {
668 show_needed = show_interp = show_bind = show_soname = \
669 show_perms = show_endian = show_size = 0;
670 for (i = 0; out_format[i]; ++i) {
671 if (!IS_MODIFIER(out_format[i])) continue;
672
673 switch (out_format[++i]) {
674 case '+': break;
675 case '%': break;
676 case '#': break;
677 case 'F': break;
678 case 'p': break;
679 case 'f': break;
680 case 'k': break;
681 case 'N': break;
682 case 'o': break;
683 case 'a': break;
684 case 'M': break;
685 case 'Z': show_size = 1; break;
686 case 'D': show_endian = 1; break;
687 case 'O': show_perms = 1; break;
688 case 'n': show_needed = 1; break;
689 case 'i': show_interp = 1; break;
690 case 'b': show_bind = 1; break;
691 case 'S': show_soname = 1; break;
692 default:
693 err("Invalid format specifier '%c' (byte %i)",
694 out_format[i], i+1);
695 }
696 }
697
698 /* construct our default format */
699 } else {
700 size_t fmt_len = 30;
701 out_format = xmalloc(sizeof(char) * fmt_len);
702 *out_format = '\0';
703 if (!be_quiet) xstrcat(&out_format, "%a ", &fmt_len);
704 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len);
705 if (show_perms) xstrcat(&out_format, "%O ", &fmt_len);
706 if (show_size) xstrcat(&out_format, "%Z ", &fmt_len);
707 if (show_endian) xstrcat(&out_format, "%D ", &fmt_len);
708 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
709 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
710 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);
711 if (show_soname) xstrcat(&out_format, "%S ", &fmt_len);
712 if (find_lib) xstrcat(&out_format, "%N ", &fmt_len);
713 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
714 }
715 if (be_verbose > 2) printf("Format: %s\n", out_format);
716
717 /* now lets actually do the scanning */
718 if (scan_envpath)
719 scanmacho_envpath();
720 if (!from_file && optind == argc && ttyname(0) == NULL && !scan_envpath)
721 from_file = "-";
722 if (from_file) {
723 scanmacho_from_file(from_file);
724 from_file = *argv;
725 }
726 if (optind == argc && !scan_envpath && !from_file)
727 err("Nothing to scan !?");
728 while (optind < argc) {
729 search_path = argv[optind++];
730 ret = scanmacho_dir(search_path);
731 }
732
733 return ret;
734 }
735
736 int main(int argc, char *argv[])
737 {
738 int ret;
739 if (argc < 2)
740 usage(EXIT_FAILURE);
741 ret = parseargs(argc, argv);
742 fclose(stdout);
743 return ret;
744 }

  ViewVC Help
Powered by ViewVC 1.1.20