options.c revision f666d191986d3b342cfa8b2e96ed90a49edf4303
1#if HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include <string.h> 6#include <stdlib.h> 7#include <unistd.h> 8#include <errno.h> 9#include <limits.h> 10 11#if HAVE_GETOPT_H 12#include <getopt.h> 13#endif 14 15#include "ltrace.h" 16#include "options.h" 17#include "defs.h" 18 19static char *progname; /* Program name (`ltrace') */ 20FILE * output; 21int opt_a = DEFAULT_ACOLUMN; /* default alignment column for results */ 22int opt_d = 0; /* debug */ 23int opt_i = 0; /* instruction pointer */ 24int opt_s = DEFAULT_STRLEN; /* default maximum # of bytes printed in strings */ 25int opt_S = 0; /* display syscalls */ 26int opt_L = 1; /* display library calls */ 27int opt_f = 0; /* trace child processes as they are created */ 28char * opt_u = NULL; /* username to run command as */ 29int opt_r = 0; /* print relative timestamp */ 30int opt_t = 0; /* print absolute timestamp */ 31#if HAVE_LIBIBERTY 32int opt_C = 0; /* Demangle low-level symbol names into user-level names */ 33#endif 34 35/* List of pids given to option -p: */ 36struct opt_p_t * opt_p = NULL; /* attach to process with a given pid */ 37 38/* List of function names given to option -e: */ 39struct opt_e_t * opt_e = NULL; 40int opt_e_enable=1; 41 42static void usage(void) 43{ 44#if !(HAVE_GETOPT || HAVE_GETOPT_LONG) 45 fprintf(stdout, "Usage: %s [command [arg ...]]\n" 46"Trace library calls of a given program.\n\n", progname); 47#else 48 fprintf(stdout, "Usage: %s [option ...] [command [arg ...]]\n" 49"Trace library calls of a given program.\n\n" 50 51# if HAVE_GETOPT_LONG 52" -d, --debug print debugging info.\n" 53# else 54" -d print debugging info.\n" 55# endif 56" -f follow forks.\n" 57" -i print instruction pointer at time of library call.\n" 58" -L do NOT display library calls.\n" 59" -S display system calls.\n" 60" -r print relative timestamps.\n" 61" -t, -tt, -ttt print absolute timestamps.\n" 62# if HAVE_LIBIBERTY 63# if HAVE_GETOPT_LONG 64" -C, --demangle decode low-level symbol names into user-level names.\n" 65# else 66" -C decode low-level symbol names into user-level names.\n" 67# endif 68# endif 69# if HAVE_GETOPT_LONG 70" -a, --align=COLUMN align return values in a secific column.\n" 71# else 72" -a COLUMN align return values in a secific column.\n" 73# endif 74" -s STRLEN specify the maximum string size to print.\n" 75# if HAVE_GETOPT_LONG 76" -o, --output=FILE write the trace output to that file.\n" 77# else 78" -o FILE write the trace output to that file.\n" 79# endif 80" -u USERNAME run command with the userid, groupid of username.\n" 81" -p PID attach to the process with the process ID pid.\n" 82" -e expr modify which events to trace.\n" 83# if HAVE_GETOPT_LONG 84" -h, --help display this help and exit.\n" 85# else 86" -h display this help and exit.\n" 87# endif 88# if HAVE_GETOPT_LONG 89" -V, --version output version information and exit.\n" 90# else 91" -V output version information and exit.\n" 92# endif 93"\nReport bugs to Juan Cespedes <cespedes@debian.org>\n" 94 , progname); 95#endif 96} 97 98static char * search_for_command(char * filename) 99{ 100 static char pathname[PATH_MAX]; 101 char *path; 102 int m, n; 103 104 if (strchr(filename, '/')) { 105 return filename; 106 } 107 for (path = getenv("PATH"); path && *path; path += m) { 108 if (strchr(path, ':')) { 109 n = strchr(path, ':') - path; 110 m = n + 1; 111 } else { 112 m = n = strlen(path); 113 } 114 strncpy(pathname, path, n); 115 if (n && pathname[n - 1] != '/') { 116 pathname[n++] = '/'; 117 } 118 strcpy(pathname + n, filename); 119 if (!access(pathname, X_OK)) { 120 return pathname; 121 } 122 } 123 return filename; 124} 125 126char ** process_options(int argc, char **argv) 127{ 128 progname = argv[0]; 129 output = stderr; 130 131#if HAVE_GETOPT || HAVE_GETOPT_LONG 132 while(1) { 133 int c; 134#if HAVE_GETOPT_LONG 135 int option_index = 0; 136 static struct option long_options[] = { 137 { "align", 1, 0, 'a'}, 138 { "debug", 0, 0, 'd'}, 139 { "demangle", 0, 0, 'C'}, 140 { "help", 0, 0, 'h'}, 141 { "output", 1, 0, 'o'}, 142 { "version", 0, 0, 'V'}, 143 { 0, 0, 0, 0} 144 }; 145 c = getopt_long(argc, argv, "+dfiLSrthV" 146# if HAVE_LIBIBERTY 147 "C" 148# endif 149 "a:s:o:u:p:e:", long_options, &option_index); 150#else 151 c = getopt(argc, argv, "+dfiLSth" 152# if HAVE_LIBIBERTY 153 "C" 154# endif 155 "a:s:o:u:p:e:"); 156#endif 157 if (c==-1) { 158 break; 159 } 160 switch(c) { 161 case 'd': opt_d++; 162 break; 163 case 'f': opt_f = 1; 164 break; 165 case 'i': opt_i++; 166 break; 167 case 'L': opt_L = 0; 168 break; 169 case 'S': opt_S = 1; 170 break; 171 case 'r': opt_r++; 172 break; 173 case 't': opt_t++; 174 break; 175#if HAVE_LIBIBERTY 176 case 'C': opt_C++; 177 break; 178#endif 179 case 'a': opt_a = atoi(optarg); 180 break; 181 case 's': opt_s = atoi(optarg); 182 break; 183 case 'h': usage(); 184 exit(0); 185 case 'o': output = fopen(optarg, "w"); 186 if (!output) { 187 fprintf(stderr, "Can't open %s for output: %s\n", optarg, strerror(errno)); 188 exit(1); 189 } 190 setvbuf(output, (char *)NULL, _IOLBF, 0); 191 break; 192 case 'u': opt_u = optarg; 193 break; 194 case 'p': 195 { 196 struct opt_p_t * tmp = malloc(sizeof(struct opt_p_t)); 197 if (!tmp) { 198 perror("malloc"); 199 exit(1); 200 } 201 tmp->pid = atoi(optarg); 202 tmp->next = opt_p; 203 opt_p = tmp; 204 break; 205 } 206 case 'e': 207 { 208 char * str_e = strdup(optarg); 209 if (!str_e) { 210 perror("strdup"); 211 exit(1); 212 } 213 if (str_e[0]=='!') { 214 opt_e_enable=0; 215 str_e++; 216 } 217 while(*str_e) { 218 struct opt_e_t * tmp; 219 char *str2 = strchr(str_e,','); 220 if (str2) { 221 *str2 = '\0'; 222 } 223 tmp = malloc(sizeof(struct opt_e_t)); 224 if (!tmp) { 225 perror("malloc"); 226 exit(1); 227 } 228 tmp->name = str_e; 229 tmp->next = opt_e; 230 opt_e = tmp; 231 if (str2) { 232 str_e = str2+1; 233 } else { 234 break; 235 } 236 } 237 break; 238 } 239 case 'V': printf("ltrace version " 240#ifdef VERSION 241 VERSION 242#else 243 "???" 244#endif 245 ".\n" 246"Copyright (C) 1997-1998 Juan Cespedes <cespedes@debian.org>.\n" 247"This is free software; see the GNU General Public Licence\n" 248"version 2 or later for copying conditions. There is NO warranty.\n"); 249 exit(0); 250 251 default: 252#if HAVE_GETOPT_LONG 253 fprintf(stderr, "Try `%s --help' for more information\n", progname); 254#else 255 fprintf(stderr, "Try `%s -h' for more information\n", progname); 256#endif 257 exit(1); 258 } 259 } 260 argc -= optind; argv += optind; 261#endif 262 263 if (!opt_p && argc<1) { 264 fprintf(stderr, "%s: too few arguments\n", progname); 265#if HAVE_GETOPT_LONG 266 fprintf(stderr, "Try `%s --help' for more information\n", progname); 267#elif HAVE_GETOPT 268 fprintf(stderr, "Try `%s -h' for more information\n", progname); 269#endif 270 exit(1); 271 } 272 if (opt_r && opt_t) { 273 fprintf(stderr, "%s: Incompatible options -r and -t\n", progname); 274 exit(1); 275 } 276 if (argc>0) { 277 command = search_for_command(argv[0]); 278 } 279 return &argv[0]; 280} 281