option handling cleanup

This commit is contained in:
Stefani Seibold 2015-05-04 11:50:39 +02:00
parent 66c24caa72
commit 033747ca32

View File

@ -3,8 +3,6 @@
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net> * Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source * This file is based on the ltrace source
* *
* This work was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich.
*
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the * published by the Free Software Foundation; either version 2 of the
@ -74,8 +72,8 @@ static void usage(void)
"\n" "\n"
" -a, --autoscan scan memory on exit of a traced program\n" " -a, --autoscan scan memory on exit of a traced program\n"
" -b, --binpath=path binary search path (may be repeated)\n" " -b, --binpath=path binary search path (may be repeated)\n"
" -c, --client connect to socket (path or address)\n" " -c, --client=addr connect to socket (path or address)\n"
" -C, --cwd set current working directory\n" " -C, --cwd=path use as current working directory for traced process\n"
#ifdef DEBUG #ifdef DEBUG
" -D, --debug=MASK enable debugging (see -Dh or --debug=help)\n" " -D, --debug=MASK enable debugging (see -Dh or --debug=help)\n"
" -Dh, --debug=help show help on debugging\n" " -Dh, --debug=help show help on debugging\n"
@ -83,7 +81,7 @@ static void usage(void)
" -d, --depth=NR backtrace stack depth (default: " STR(DEFAULT_STACK) ")\n" " -d, --depth=NR backtrace stack depth (default: " STR(DEFAULT_STACK) ")\n"
" -e, --follow-exec follow exec() system calls\n" " -e, --follow-exec follow exec() system calls\n"
" -F, --config=FILE load alternate configuration file (may be repeated)\n" " -F, --config=FILE load alternate configuration file (may be repeated)\n"
" -f, --follow-child trace forked children\n" " -f, --follow-fork trace forked children\n"
" -h, --help display this help and exit\n" " -h, --help display this help and exit\n"
" -i, --interactive interactive client mode\n" " -i, --interactive interactive client mode\n"
" -k, --kill abort mtrace on unexpected error conditon\n" " -k, --kill abort mtrace on unexpected error conditon\n"
@ -126,9 +124,9 @@ static char *search_for_command(char *filename)
char *path; char *path;
int m, n; int m, n;
if (strchr(filename, '/')) { if (strchr(filename, '/'))
return filename; return filename;
}
for (path = getenv("PATH"); path && *path; path += m) { for (path = getenv("PATH"); path && *path; path += m) {
if (strchr(path, ':')) { if (strchr(path, ':')) {
n = strchr(path, ':') - path; n = strchr(path, ':') - path;
@ -136,18 +134,21 @@ static char *search_for_command(char *filename)
} else { } else {
m = n = strlen(path); m = n = strlen(path);
} }
if (n + strlen(filename) + 1 >= PATH_MAX) { if (n + strlen(filename) + 1 >= PATH_MAX) {
fprintf(stderr, "Error: filename too long.\n"); fprintf(stderr, "Error: filename too long.\n");
exit(1); exit(1);
} }
strncpy(pathname, path, n); strncpy(pathname, path, n);
if (n && pathname[n - 1] != '/') {
if (n && pathname[n - 1] != '/')
pathname[n++] = '/'; pathname[n++] = '/';
}
strcpy(pathname + n, filename); strcpy(pathname + n, filename);
if (!access(pathname, X_OK)) {
if (!access(pathname, X_OK))
return pathname; return pathname;
}
} }
return filename; return filename;
} }
@ -192,28 +193,31 @@ static void def_config(void)
if (path) { if (path) {
if (asprintf(&filename, "%s/.mtrace", path) != -1) { if (asprintf(&filename, "%s/.mtrace", path) != -1) {
if (add_opt_F(filename)) if (!add_opt_F(filename))
free(filename); return;
free(filename);
} }
} }
else {
path = getenv("XDG_CONFIG_HOME"); path = getenv("XDG_CONFIG_HOME");
if (path) { if (path) {
if (asprintf(&filename, "%s/mtrace", path) != -1) { if (asprintf(&filename, "%s/mtrace", path) != -1) {
if (add_opt_F(filename)) if (!add_opt_F(filename))
free(filename); return;
} free(filename);
} }
} }
if (asprintf(&filename, "%s/mtrace.conf", SYSCONFDIR) != -1) { if (asprintf(&filename, "%s/mtrace.conf", SYSCONFDIR) != -1) {
if (add_opt_F(filename)) if (!add_opt_F(filename))
free(filename); return;
free(filename);
} }
else
if (asprintf(&filename, "%s/mtrace.conf", "/etc") != -1) { if (asprintf(&filename, "%s/mtrace.conf", "/etc") != -1) {
if (add_opt_F(filename)) if (!add_opt_F(filename))
free(filename); return;
free(filename);
} }
} }
@ -232,6 +236,8 @@ static int parse_int(const char *optarg, char opt, int min, int max)
char **process_options(int argc, char **argv) char **process_options(int argc, char **argv)
{ {
char *output = NULL;
progname = argv[0]; progname = argv[0];
options.auto_scan = 0; options.auto_scan = 0;
@ -268,7 +274,7 @@ char **process_options(int argc, char **argv)
{ "debug", 1, 0, 'D' }, { "debug", 1, 0, 'D' },
{ "depth", 1, 0, 'd' }, { "depth", 1, 0, 'd' },
{ "help", 0, 0, 'h' }, { "help", 0, 0, 'h' },
{ "follow-child", 0, 0, 'f'}, { "follow-fork", 0, 0, 'f'},
{ "follow-exec", 0, 0, 'e' }, { "follow-exec", 0, 0, 'e' },
{ "interactive", 0, 0, 'i' }, { "interactive", 0, 0, 'i' },
{ "kill", 0, 0, 'k' }, { "kill", 0, 0, 'k' },
@ -363,13 +369,7 @@ char **process_options(int argc, char **argv)
options.listen = optarg; options.listen = optarg;
break; break;
case 'o': case 'o':
options.output = fopen(optarg, "w"); output = optarg;
if (!options.output) {
fprintf(stderr, "can't open %s for writing: %s\n", optarg, strerror(errno));
exit(1);
}
setvbuf(options.output, (char *)NULL, _IOLBF, 0);
fcntl(fileno(options.output), F_SETFD, FD_CLOEXEC);
break; break;
case 'p': case 'p':
{ {
@ -460,6 +460,9 @@ char **process_options(int argc, char **argv)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc > 0)
options.command = search_for_command(argv[0]);
if (options.sort_by == OPT_SORT_LEAKS || options.sort_by == OPT_SORT_BYTES_LEAKED) if (options.sort_by == OPT_SORT_LEAKS || options.sort_by == OPT_SORT_BYTES_LEAKED)
options.auto_scan = 1; options.auto_scan = 1;
@ -489,9 +492,15 @@ char **process_options(int argc, char **argv)
err_usage(); err_usage();
} }
if (options.interactive && (!options.client && !options.opt_p)) { if (options.interactive) {
fprintf(stderr, "%s: interactive mode can only invoked in -p or -c mode\n", progname); if ((!options.client && !options.opt_p) || options.command) {
err_usage(); fprintf(stderr, "%s: interactive mode can only invoked in -p or -c mode\n", progname);
err_usage();
}
output = NULL;
if (options.auto_scan)
fprintf(stderr, "%s: auto scan ignored in interactive mode\n", progname);
} }
if (options.auto_scan && options.server) { if (options.auto_scan && options.server) {
@ -522,8 +531,16 @@ char **process_options(int argc, char **argv)
if (!options.opt_F) if (!options.opt_F)
def_config(); def_config();
if (argc > 0) if (output) {
options.command = search_for_command(argv[0]); options.output = fopen(output, "w");
if (!options.output) {
fprintf(stderr, "can't open %s for writing: %s\n", output, strerror(errno));
exit(1);
}
setvbuf(options.output, (char *)NULL, _IOLBF, 0);
fcntl(fileno(options.output), F_SETFD, FD_CLOEXEC);
}
return &argv[0]; return &argv[0];
} }