• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2012, 2013, 2014 Petr Machata, Red Hat Inc.
4  * Copyright (C) 2009,2010 Joe Damato
5  * Copyright (C) 1998,1999,2002,2003,2004,2007,2008,2009 Juan Cespedes
6  * Copyright (C) 2006 Ian Wienand
7  * Copyright (C) 2006 Steve Fink
8  * Copyright (C) 2006 Paul Gilliam, IBM Corporation
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of the
13  * License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25 
26 #include "config.h"
27 
28 #include <sys/ioctl.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <getopt.h>
35 #include <limits.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 #include "common.h"
42 #include "filter.h"
43 #include "glob.h"
44 #include "demangle.h"
45 
46 struct options_t options = {
47 	.align    = DEFAULT_ALIGN,    /* alignment column for results */
48 	.user     = NULL,             /* username to run command as */
49 	.syscalls = 0,                /* display syscalls */
50 #ifdef USE_DEMANGLE
51 	.demangle = 0,                /* Demangle low-level symbol names */
52 #endif
53 	.indent = 0,                  /* indent output according to program flow */
54 	.output = NULL,               /* output to a specific file */
55 	.summary = 0,                 /* Report a summary on program exit */
56 	.debug = 0,                   /* debug */
57 	.arraylen = DEFAULT_ARRAYLEN, /* maximum # array elements to print */
58 	.strlen = DEFAULT_STRLEN,     /* maximum # of bytes printed in strings */
59 	.follow = 0,                  /* trace child processes */
60 };
61 
62 static char *progname;		/* Program name (`ltrace') */
63 int opt_i = 0;			/* instruction pointer */
64 int opt_r = 0;			/* print relative timestamp */
65 int opt_t = 0;			/* print absolute timestamp */
66 int opt_T = 0;			/* show the time spent inside each call */
67 
68 /* List of pids given to option -p: */
69 struct opt_p_t *opt_p = NULL;	/* attach to process with a given pid */
70 
71 /* Vector of struct opt_F_t.  */
72 struct vect opt_F;
73 
74 static void
err_usage(void)75 err_usage(void) {
76 	fprintf(stderr, "Try `%s --help' for more information.\n", progname);
77 	exit(1);
78 }
79 
80 static void
usage(void)81 usage(void) {
82 	fprintf(stdout, "Usage: %s [option ...] [command [arg ...]]\n"
83 		"Trace library calls of a given program.\n\n"
84 		"  -a, --align=COLUMN  align return values in a secific column.\n"
85 		"  -A MAXELTS          maximum number of array elements to print.\n"
86 		"  -b, --no-signals    don't print signals.\n"
87 		"  -c                  count time and calls, and report a summary on exit.\n"
88 # ifdef USE_DEMANGLE
89 		"  -C, --demangle      decode low-level symbol names into user-level names.\n"
90 # endif
91 		"  -D, --debug=MASK    enable debugging (see -Dh or --debug=help).\n"
92 		"  -Dh, --debug=help   show help on debugging.\n"
93 		"  -e FILTER           modify which library calls to trace.\n"
94 		"  -f                  trace children (fork() and clone()).\n"
95 		"  -F, --config=FILE   load alternate configuration file (may be repeated).\n"
96 		"  -h, --help          display this help and exit.\n"
97 		"  -i                  print instruction pointer at time of library call.\n"
98 		"  -l, --library=LIBRARY_PATTERN only trace symbols implemented by this library.\n"
99 		"  -L                  do NOT display library calls.\n"
100 		"  -n, --indent=NR     indent output by NR spaces for each call level nesting.\n"
101 		"  -o, --output=FILENAME write the trace output to file with given name.\n"
102 		"  -p PID              attach to the process with the process ID pid.\n"
103 		"  -r                  print relative timestamps.\n"
104 		"  -s STRSIZE          specify the maximum string size to print.\n"
105 		"  -S                  trace system calls as well as library calls.\n"
106 		"  -t, -tt, -ttt       print absolute timestamps.\n"
107 		"  -T                  show the time spent inside each call.\n"
108 		"  -u USERNAME         run command with the userid, groupid of username.\n"
109 		"  -V, --version       output version information and exit.\n"
110 #if defined(HAVE_UNWINDER)
111 		"  -w, --where=NR      print backtrace showing NR stack frames at most.\n"
112 #endif /* defined(HAVE_UNWINDER) */
113 		"  -x FILTER           modify which static functions to trace.\n"
114 		"\nReport bugs to ltrace-devel@lists.alioth.debian.org\n",
115 		progname);
116 }
117 
118 static void
usage_debug(void)119 usage_debug(void) {
120 	fprintf(stdout, "%s debugging option, --debug=<octal> or -D<octal>:\n", progname);
121 	fprintf(stdout,
122 			"\n"
123 			" number  ref. in source   description\n"
124 			"      1   general           Generally helpful progress information\n"
125 			"     10   event             Shows every event received by a traced process\n"
126 			"     20   process           Shows actions carried upon a traced processes\n"
127 			"     40   function          Shows every entry to internal functions\n"
128 			"\n"
129 			"Debugging options are mixed using bitwise-or.\n"
130 			"Note that the meanings and values are subject to change.\n"
131 			"Also note that these values are used inconsistently in ltrace, and the\n"
132 			"only debuglevel that you can rely on is -D77 that will show everything.\n"
133 		   );
134 }
135 
136 static char *
search_for_command(char * filename)137 search_for_command(char *filename) {
138 	static char pathname[PATH_MAX];
139 	char *path;
140 	int m, n;
141 
142 	if (strchr(filename, '/')) {
143 		return filename;
144 	}
145 	for (path = getenv("PATH"); path && *path; path += m) {
146 		if (strchr(path, ':')) {
147 			n = strchr(path, ':') - path;
148 			m = n + 1;
149 		} else {
150 			m = n = strlen(path);
151 		}
152 		if (n + strlen(filename) + 1 >= PATH_MAX) {
153 			fprintf(stderr, "Error: filename too long.\n");
154 			exit(1);
155 		}
156 		strncpy(pathname, path, n);
157 		if (n && pathname[n - 1] != '/') {
158 			pathname[n++] = '/';
159 		}
160 		strcpy(pathname + n, filename);
161 		if (!access(pathname, X_OK)) {
162 			return pathname;
163 		}
164 	}
165 	return filename;
166 }
167 
168 static void
guess_cols(void)169 guess_cols(void) {
170 	struct winsize ws;
171 	char *c;
172 
173 	options.align = DEFAULT_ALIGN;
174 	c = getenv("COLUMNS");
175 	if (c && *c) {
176 		char *endptr;
177 		int cols;
178 		cols = strtol(c, &endptr, 0);
179 		if (cols > 0 && !*endptr) {
180 			options.align = cols * 5 / 8;
181 		}
182 	} else if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 0) {
183 		options.align = ws.ws_col * 5 / 8;
184 	} else if (ioctl(2, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 0) {
185 		options.align = ws.ws_col * 5 / 8;
186 	}
187 }
188 
189 static int
compile_libname(const char * expr,const char * a_lib,int lib_re_p,struct filter_lib_matcher * matcher)190 compile_libname(const char *expr, const char *a_lib, int lib_re_p,
191 		struct filter_lib_matcher *matcher)
192 {
193 	if (strcmp(a_lib, "MAIN") == 0) {
194 		filter_lib_matcher_main_init(matcher);
195 	} else {
196 		/* Add ^ and $ to the library expression as well.  */
197 		char lib[strlen(a_lib) + 3];
198 		sprintf(lib, "^%s$", a_lib);
199 
200 		enum filter_lib_matcher_type type
201 			= lib[0] == '/' ? FLM_PATHNAME : FLM_SONAME;
202 
203 		regex_t lib_re;
204 		int status = (lib_re_p ? regcomp : globcomp)(&lib_re, lib, 0);
205 		if (status != 0) {
206 			char buf[100];
207 			regerror(status, &lib_re, buf, sizeof buf);
208 			fprintf(stderr, "Couldn't compile '%s': %s.\n",
209 				expr, buf);
210 			return -1;
211 		}
212 		filter_lib_matcher_name_init(matcher, type, lib_re);
213 	}
214 	return 0;
215 }
216 
217 static int
add_filter_rule(struct filter * filt,const char * expr,enum filter_rule_type type,const char * a_sym,int sym_re_p,const char * a_lib,int lib_re_p)218 add_filter_rule(struct filter *filt, const char *expr,
219 		enum filter_rule_type type,
220 		const char *a_sym, int sym_re_p,
221 		const char *a_lib, int lib_re_p)
222 {
223 	struct filter_rule *rule = malloc(sizeof(*rule));
224 	struct filter_lib_matcher *matcher = malloc(sizeof(*matcher));
225 
226 	if (rule == NULL || matcher == NULL) {
227 	fail:
228 		free(rule);
229 		free(matcher);
230 		return -1;
231 	}
232 
233 	regex_t symbol_re;
234 	{
235 		/* Add ^ to the start of expression and $ to the end, so that
236 		 * we match the whole symbol name.  Let the user write the "*"
237 		 * explicitly if they wish.  */
238 		char sym[strlen(a_sym) + 3];
239 		sprintf(sym, "^%s$", a_sym);
240 		int status = (sym_re_p ? regcomp : globcomp)
241 			(&symbol_re, sym, 0);
242 		if (status != 0) {
243 			char buf[100];
244 			regerror(status, &symbol_re, buf, sizeof buf);
245 			fprintf(stderr, "Couldn't compile '%s': %s.\n",
246 				expr, buf);
247 			goto fail;
248 		}
249 	}
250 
251 	if (compile_libname(expr, a_lib, lib_re_p, matcher) < 0) {
252 		regfree(&symbol_re);
253 		goto fail;
254 	}
255 
256 	filter_rule_init(rule, type, matcher, symbol_re);
257 	filter_add_rule(filt, rule);
258 	return 0;
259 }
260 
261 static int
grok_libname_pattern(char ** libnamep,char ** libendp)262 grok_libname_pattern(char **libnamep, char **libendp)
263 {
264 	char *libname = *libnamep;
265 	char *libend = *libendp;
266 
267 	if (libend[0] != '/')
268 		return 0;
269 
270 	*libend-- = 0;
271 	if (libname != libend && libname[0] == '/')
272 		++libname;
273 	else
274 		fprintf(stderr, "Unmatched '/' in library name.\n");
275 
276 	*libendp = libend;
277 	*libnamep = libname;
278 	return 1;
279 }
280 
281 static int
parse_filter(struct filter * filt,char * expr,int operators)282 parse_filter(struct filter *filt, char *expr, int operators)
283 {
284 	/* Filter is a chain of sym@lib rules separated by '-' or '+'.
285 	 * If the filter expression starts with '-', the missing
286 	 * initial rule is implicitly *@*.  */
287 
288 	enum filter_rule_type type = FR_ADD;
289 
290 	while (*expr != 0) {
291 		size_t s = strcspn(expr, &"-+@"[operators ? 0 : 2]);
292 		char *symname = expr;
293 		char *libname;
294 		char *next = expr + s + 1;
295 		enum filter_rule_type this_type = type;
296 
297 		if (expr[s] == 0) {
298 			libname = "*";
299 			expr = next - 1;
300 
301 		} else if (expr[s] == '-' || expr[s] == '+') {
302 			type = expr[s] == '-' ? FR_SUBTRACT : FR_ADD;
303 			expr[s] = 0;
304 			libname = "*";
305 			expr = next;
306 
307 		} else {
308 			assert(expr[s] == '@');
309 			expr[s] = 0;
310 			s = strcspn(next, &"-+"[operators ? 0 : 2]);
311 			if (s == 0) {
312 				libname = "*";
313 				expr = next;
314 			} else if (next[s] == 0) {
315 				expr = next + s;
316 				libname = next;
317 			} else {
318 				assert(next[s] == '-' || next[s] == '+');
319 				type = next[s] == '-' ? FR_SUBTRACT : FR_ADD;
320 				next[s] = 0;
321 				expr = next + s + 1;
322 				libname = next;
323 			}
324 		}
325 
326 		assert(*libname != 0);
327 		char *symend = symname + strlen(symname) - 1;
328 		char *libend = libname + strlen(libname) - 1;
329 		int sym_is_re = 0;
330 		int lib_is_re = 0;
331 
332 		/*
333 		 * /xxx/@... and ...@/xxx/ means that xxx are regular
334 		 * expressions.  They are globs otherwise.
335 		 *
336 		 * /xxx@yyy/ is the same as /xxx/@/yyy/
337 		 *
338 		 * @/xxx matches library path name
339 		 * @.xxx matches library relative path name
340 		 */
341 		if (symname[0] == '/') {
342 			if (symname != symend && symend[0] == '/') {
343 				++symname;
344 				*symend-- = 0;
345 				sym_is_re = 1;
346 
347 			} else {
348 				sym_is_re = 1;
349 				lib_is_re = 1;
350 				++symname;
351 
352 				/* /XXX@YYY/ is the same as
353 				 * /XXX/@/YYY/.  */
354 				if (libend[0] != '/')
355 					fprintf(stderr, "Unmatched '/'"
356 						" in symbol name.\n");
357 				else
358 					*libend-- = 0;
359 			}
360 		}
361 
362 		/* If libname ends in '/', then we expect '/' in the
363 		 * beginning too.  Otherwise the initial '/' is part
364 		 * of absolute file name.  */
365 		if (!lib_is_re)
366 			lib_is_re = grok_libname_pattern(&libname, &libend);
367 
368 		if (*symname == 0) /* /@AA/ */
369 			symname = "*";
370 		if (*libname == 0) /* /aa@/ */
371 			libname = "*";
372 
373 		add_filter_rule(filt, expr, this_type,
374 				symname, sym_is_re,
375 				libname, lib_is_re);
376 	}
377 
378 	return 0;
379 }
380 
381 static struct filter *
recursive_parse_chain(const char * orig,char * expr,int operators)382 recursive_parse_chain(const char *orig, char *expr, int operators)
383 {
384 	struct filter *filt = malloc(sizeof(*filt));
385 	if (filt == NULL) {
386 		fprintf(stderr, "(Part of) filter will be ignored: '%s': %s.\n",
387 			expr, strerror(errno));
388 		return NULL;
389 	}
390 
391 	filter_init(filt);
392 	if (parse_filter(filt, expr, operators) < 0) {
393 		fprintf(stderr, "Filter '%s' will be ignored.\n", orig);
394 		free(filt);
395 		filt = NULL;
396 	}
397 
398 	return filt;
399 }
400 
401 static struct filter **
slist_chase_end(struct filter ** begin)402 slist_chase_end(struct filter **begin)
403 {
404 	for (; *begin != NULL; begin = &(*begin)->next)
405 		;
406 	return begin;
407 }
408 
409 static void
parse_filter_chain(const char * expr,struct filter ** retp)410 parse_filter_chain(const char *expr, struct filter **retp)
411 {
412 	char *str = strdup(expr);
413 	if (str == NULL) {
414 		fprintf(stderr, "Filter '%s' will be ignored: %s.\n",
415 			expr, strerror(errno));
416 		return;
417 	}
418 	/* Support initial '!' for backward compatibility.  */
419 	if (str[0] == '!')
420 		str[0] = '-';
421 
422 	*slist_chase_end(retp) = recursive_parse_chain(expr, str, 1);
423 	free(str);
424 }
425 
426 static int
parse_int(const char * optarg,char opt,int min,int max)427 parse_int(const char *optarg, char opt, int min, int max)
428 {
429 	char *endptr;
430 	long int l = strtol(optarg, &endptr, 0);
431 	if (l < min || (max != 0 && l > max)
432 	    || *optarg == 0 || *endptr != 0) {
433 		const char *fmt = max != 0
434 			? "Invalid argument to -%c: '%s'.  Use integer %d..%d.\n"
435 			: "Invalid argument to -%c: '%s'.  Use integer >=%d.\n";
436 		fprintf(stderr, fmt, opt, optarg, min, max);
437 		exit(1);
438 	}
439 	return (int)l;
440 }
441 
442 int
parse_colon_separated_list(const char * paths,struct vect * vec)443 parse_colon_separated_list(const char *paths, struct vect *vec)
444 {
445 	/* PATHS contains a colon-separated list of directories and
446 	 * files to load.  It's modeled after shell PATH variable,
447 	 * which doesn't allow escapes.  PYTHONPATH in CPython behaves
448 	 * the same way.  So let's follow suit, it makes things easier
449 	 * to us.  */
450 
451 	char *clone = strdup(paths);
452 	if (clone == NULL) {
453 		fprintf(stderr, "Couldn't parse argument %s: %s.\n",
454 			paths, strerror(errno));
455 		return -1;
456 	}
457 
458 	/* It's undesirable to use strtok, because we want the string
459 	 * "a::b" to have three elements.  */
460 	char *tok = clone - 1;
461 	char *end = clone + strlen(clone);
462 	while (tok < end) {
463 		++tok;
464 		size_t len = strcspn(tok, ":");
465 		tok[len] = 0;
466 
467 		struct opt_F_t arg = {
468 			.pathname = tok,
469 			.own_pathname = tok == clone,
470 		};
471 		if (VECT_PUSHBACK(vec, &arg) < 0)
472 			/* Presumably this is not a deal-breaker.  */
473 			fprintf(stderr, "Couldn't store component of %s: %s.\n",
474 				paths, strerror(errno));
475 
476 		tok += len;
477 	}
478 
479 	return 0;
480 }
481 
482 void
opt_F_destroy(struct opt_F_t * entry)483 opt_F_destroy(struct opt_F_t *entry)
484 {
485 	if (entry == NULL)
486 		return;
487 	if (entry->own_pathname)
488 		free(entry->pathname);
489 }
490 
491 enum opt_F_kind
opt_F_get_kind(struct opt_F_t * entry)492 opt_F_get_kind(struct opt_F_t *entry)
493 {
494 	if (entry->kind == OPT_F_UNKNOWN) {
495 		struct stat st;
496 		if (lstat(entry->pathname, &st) < 0) {
497 			fprintf(stderr, "Couldn't stat %s: %s\n",
498 				entry->pathname, strerror(errno));
499 			entry->kind = OPT_F_BROKEN;
500 		} else if (S_ISDIR(st.st_mode)) {
501 			entry->kind = OPT_F_DIR;
502 		} else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
503 			entry->kind = OPT_F_FILE;
504 		} else {
505 			fprintf(stderr, "%s is neither a regular file, "
506 				"nor a directory.\n", entry->pathname);
507 			entry->kind = OPT_F_BROKEN;
508 		}
509 	}
510 	assert(entry->kind != OPT_F_UNKNOWN);
511 	return entry->kind;
512 }
513 
514 char **
process_options(int argc,char ** argv)515 process_options(int argc, char **argv)
516 {
517 	VECT_INIT(&opt_F, struct opt_F_t);
518 
519 	progname = argv[0];
520 	options.output = stderr;
521 	options.no_signals = 0;
522 #if defined(HAVE_UNWINDER)
523 	options.bt_depth = -1;
524 #endif /* defined(HAVE_UNWINDER) */
525 
526 	guess_cols();
527 
528 	int libcalls = 1;
529 
530 	while (1) {
531 		int c;
532 		char *p;
533 #ifdef HAVE_GETOPT_LONG
534 		int option_index = 0;
535 		static struct option long_options[] = {
536 			{"align", 1, 0, 'a'},
537 			{"config", 1, 0, 'F'},
538 			{"debug", 1, 0, 'D'},
539 # ifdef USE_DEMANGLE
540 			{"demangle", 0, 0, 'C'},
541 # endif
542 			{"indent", 1, 0, 'n'},
543 			{"help", 0, 0, 'h'},
544 			{"library", 1, 0, 'l'},
545 			{"output", 1, 0, 'o'},
546 			{"version", 0, 0, 'V'},
547 			{"no-signals", 0, 0, 'b'},
548 # if defined(HAVE_UNWINDER)
549 			{"where", 1, 0, 'w'},
550 # endif /* defined(HAVE_UNWINDER) */
551 			{0, 0, 0, 0}
552 		};
553 #endif
554 
555 		const char *opts = "+"
556 #ifdef USE_DEMANGLE
557 			"C"
558 #endif
559 #if defined(HAVE_UNWINDER)
560 			"w:"
561 #endif
562 			"cfhiLrStTVba:A:D:e:F:l:n:o:p:s:u:x:";
563 
564 #ifdef HAVE_GETOPT_LONG
565 		c = getopt_long(argc, argv, opts, long_options, &option_index);
566 #else
567 		c = getopt(argc, argv, opts);
568 #endif
569 		if (c == -1) {
570 			break;
571 		}
572 		switch (c) {
573 		case 'a':
574 			options.align = parse_int(optarg, 'a', 0, 0);
575 			break;
576 		case 'A':
577 			options.arraylen = parse_int(optarg, 'A', 0, 0);
578 			break;
579 		case 'b':
580 			options.no_signals = 1;
581 			break;
582 		case 'c':
583 			options.summary++;
584 			break;
585 #ifdef USE_DEMANGLE
586 		case 'C':
587 			options.demangle++;
588 			break;
589 #endif
590 		case 'D':
591 			if (optarg[0]=='h') {
592 				usage_debug();
593 				exit(0);
594 			}
595 			options.debug = strtoul(optarg,&p,8);
596 			if (*p) {
597 				fprintf(stderr, "%s: --debug requires an octal argument\n", progname);
598 				err_usage();
599 			}
600 			break;
601 
602 		case 'e':
603 			parse_filter_chain(optarg, &options.plt_filter);
604 			break;
605 
606 		case 'f':
607 			options.follow = 1;
608 			break;
609 		case 'F':
610 			parse_colon_separated_list(optarg, &opt_F);
611 			break;
612 		case 'h':
613 			usage();
614 			exit(0);
615 		case 'i':
616 			opt_i++;
617 			break;
618 
619 		case 'l': {
620 			size_t patlen = strlen(optarg);
621 			char buf[patlen + 2];
622 			sprintf(buf, "@%s", optarg);
623 			*slist_chase_end(&options.export_filter)
624 				= recursive_parse_chain(buf, buf, 0);
625 			break;
626 		}
627 
628 		case 'L':
629 			libcalls = 0;
630 			break;
631 		case 'n':
632 			options.indent = parse_int(optarg, 'n', 0, 20);
633 			break;
634 		case 'o':
635 			options.output = fopen(optarg, "w");
636 			if (!options.output) {
637 				fprintf(stderr,
638 					"can't open %s for writing: %s\n",
639 					optarg, strerror(errno));
640 				exit(1);
641 			}
642 			setvbuf(options.output, (char *)NULL, _IOLBF, 0);
643 			fcntl(fileno(options.output), F_SETFD, FD_CLOEXEC);
644 			break;
645 		case 'p':
646 			{
647 				struct opt_p_t *tmp = malloc(sizeof(struct opt_p_t));
648 				if (!tmp) {
649 					perror("ltrace: malloc");
650 					exit(1);
651 				}
652 				tmp->pid = parse_int(optarg, 'p', 1, 0);
653 				tmp->next = opt_p;
654 				opt_p = tmp;
655 				break;
656 			}
657 		case 'r':
658 			opt_r++;
659 			break;
660 		case 's':
661 			options.strlen = parse_int(optarg, 's', 0, 0);
662 			break;
663 		case 'S':
664 			options.syscalls = 1;
665 			break;
666 		case 't':
667 			opt_t++;
668 			break;
669 		case 'T':
670 			opt_T++;
671 			break;
672 		case 'u':
673 			options.user = optarg;
674 			break;
675 		case 'V':
676 			printf("ltrace " PACKAGE_VERSION "\n"
677 			       "Copyright (C) 2010-2013 Petr Machata, Red Hat Inc.\n"
678 			       "Copyright (C) 1997-2009 Juan Cespedes <cespedes@debian.org>.\n"
679 			       "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
680 			       "This is free software: you are free to change and redistribute it.\n"
681 			       "There is NO WARRANTY, to the extent permitted by law.\n");
682 			exit(0);
683 			break;
684 #if defined(HAVE_UNWINDER)
685 		case 'w':
686 			options.bt_depth = parse_int(optarg, 'w', 1, 0);
687 			break;
688 #endif /* defined(HAVE_UNWINDER) */
689 
690 		case 'x':
691 			parse_filter_chain(optarg, &options.static_filter);
692 			break;
693 
694 		default:
695 			err_usage();
696 		}
697 	}
698 	argc -= optind;
699 	argv += optind;
700 
701 	/* If neither -e, nor -l, nor -L are used, set default -e.
702 	 * Use @MAIN for now, as that's what ltrace used to have in
703 	 * the past.  XXX Maybe we should make this "*" instead.  */
704 	if (libcalls
705 	    && options.plt_filter == NULL
706 	    && options.export_filter == NULL) {
707 		parse_filter_chain("@MAIN", &options.plt_filter);
708 		options.hide_caller = 1;
709 	}
710 	if (!libcalls && options.plt_filter != NULL) {
711 		fprintf(stderr,
712 			"%s: Option -L can't be used with -e or -l.\n",
713 			progname);
714 		err_usage();
715 	}
716 
717 	if (!opt_p && argc < 1) {
718 		fprintf(stderr, "%s: too few arguments\n", progname);
719 		err_usage();
720 	}
721 	if (opt_r && opt_t) {
722 		fprintf(stderr,
723 			"%s: Options -r and -t can't be used together\n",
724 			progname);
725 		err_usage();
726 	}
727 	if (argc > 0) {
728 		command = search_for_command(argv[0]);
729 	}
730 	return &argv[0];
731 }
732