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

Contents of /pax-utils/scanmacho.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19 - (show annotations) (download) (as text)
Wed Dec 8 00:54:40 2010 UTC (3 years, 7 months ago) by vapier
Branch: MAIN
Changes since 1.18: +3 -3 lines
File MIME type: text/x-csrc
change to simpler const argv0 string

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

  ViewVC Help
Powered by ViewVC 1.1.20