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