| #include <string.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <limits.h> |
| |
| #include "ltrace.h" |
| #include "options.h" |
| #include "defs.h" |
| |
| FILE * output; |
| int opt_a = DEFAULT_ACOLUMN; /* default alignment column for results */ |
| int opt_d = 0; /* debug */ |
| int opt_i = 0; /* instruction pointer */ |
| int opt_s = DEFAULT_STRLEN; /* default maximum # of bytes printed in strings */ |
| int opt_S = 0; /* display syscalls */ |
| int opt_L = 1; /* display library calls */ |
| int opt_f = 0; /* trace child processes as they are created */ |
| |
| /* List of pids given to option -p: */ |
| struct opt_p_t * opt_p = NULL; /* attach to process with a given pid */ |
| |
| static void usage(void) |
| { |
| fprintf(stderr, "Usage: ltrace [-dfiLS] [-a column] [-s strlen] [-o filename]\n" |
| " [-p pid] ... [command [arg ...]]\n\n"); |
| } |
| |
| static char * search_for_command(char * filename) |
| { |
| static char pathname[PATH_MAX]; |
| char *path; |
| int m, n; |
| |
| if (strchr(filename, '/')) { |
| return filename; |
| } |
| for (path = getenv("PATH"); path && *path; path += m) { |
| if (strchr(path, ':')) { |
| n = strchr(path, ':') - path; |
| m = n + 1; |
| } else { |
| m = n = strlen(path); |
| } |
| strncpy(pathname, path, n); |
| if (n && pathname[n - 1] != '/') { |
| pathname[n++] = '/'; |
| } |
| strcpy(pathname + n, filename); |
| if (!access(pathname, X_OK)) { |
| return pathname; |
| } |
| } |
| return filename; |
| } |
| |
| char ** process_options(int argc, char **argv) |
| { |
| char *nextchar = NULL; |
| |
| output = stderr; |
| |
| while(1) { |
| if (!nextchar || !(*nextchar)) { |
| if (!argv[1] || argv[1][0] != '-' || !argv[1][1]) { |
| break; |
| } |
| nextchar = &argv[1][1]; |
| argc--; argv++; |
| } |
| switch (*nextchar++) { |
| case 'a': opt_a = atoi(argv[1]); |
| argc--; argv++; |
| break; |
| case 'd': opt_d++; |
| break; |
| case 'o': output = fopen(argv[1], "w"); |
| if (!output) { |
| fprintf(stderr, "Can't open %s for output: %s\n", argv[1], strerror(errno)); |
| exit(1); |
| } |
| argc--; argv++; |
| break; |
| case 'i': opt_i++; |
| break; |
| case 's': opt_s = atoi(argv[1]); |
| argc--; argv++; |
| break; |
| case 'L': opt_L = 0; |
| break; |
| case 'S': opt_S = 1; |
| break; |
| case 'f': opt_f = 1; |
| break; |
| case 'p': |
| { |
| struct opt_p_t * tmp = malloc(sizeof(struct opt_p_t)); |
| if (!tmp) { |
| perror("malloc"); |
| exit(1); |
| } |
| tmp->pid = atoi(argv[1]); |
| argc--; argv++; |
| break; |
| } |
| default: fprintf(stderr, "Unknown option '%c'\n", *(nextchar-1)); |
| usage(); |
| exit(1); |
| } |
| } |
| |
| if (argc<2) { |
| usage(); |
| exit(1); |
| } |
| command = search_for_command(argv[1]); |
| return &argv[1]; |
| } |