17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*f07a2a2eScraigm 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/wait.h> 367c478bd9Sstevel@tonic-gate #include <apptrace.h> 377c478bd9Sstevel@tonic-gate #include <libintl.h> 387c478bd9Sstevel@tonic-gate #include <locale.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #ifdef TRUE 417c478bd9Sstevel@tonic-gate #undef TRUE 427c478bd9Sstevel@tonic-gate #endif 437c478bd9Sstevel@tonic-gate #ifdef FALSE 447c478bd9Sstevel@tonic-gate #undef FALSE 457c478bd9Sstevel@tonic-gate #endif 467c478bd9Sstevel@tonic-gate #define TRUE 1 477c478bd9Sstevel@tonic-gate #define FALSE 0 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* Various list pointers */ 507c478bd9Sstevel@tonic-gate static char *fromlist; 517c478bd9Sstevel@tonic-gate static char *fromexcl; 527c478bd9Sstevel@tonic-gate static char *tolist; 537c478bd9Sstevel@tonic-gate static char *toexcl; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static char *iflist; 567c478bd9Sstevel@tonic-gate static char *ifexcl; 577c478bd9Sstevel@tonic-gate static char *viflist; 587c478bd9Sstevel@tonic-gate static char *vifexcl; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* The supported options */ 617c478bd9Sstevel@tonic-gate static char const *optlet = "F:fo:T:t:v:"; 627c478bd9Sstevel@tonic-gate /* basename(argv[0]) */ 637c478bd9Sstevel@tonic-gate static char const *command; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* The environment variables that'll get picked up by apptrace.so.1 */ 667c478bd9Sstevel@tonic-gate static char const *APPTRACE_BINDTO = "APPTRACE_BINDTO="; 677c478bd9Sstevel@tonic-gate static char const *APPTRACE_BINDTO_EXCLUDE = "APPTRACE_BINDTO_EXCLUDE="; 687c478bd9Sstevel@tonic-gate static char const *APPTRACE_BINDFROM = "APPTRACE_BINDFROM="; 697c478bd9Sstevel@tonic-gate static char const *APPTRACE_BINDFROM_EXCLUDE = "APPTRACE_BINDFROM_EXCLUDE="; 707c478bd9Sstevel@tonic-gate static char const *APPTRACE_OUTPUT = "APPTRACE_OUTPUT="; 717c478bd9Sstevel@tonic-gate static char const *APPTRACE_PID = "APPTRACE_PID="; 727c478bd9Sstevel@tonic-gate static char const *APPTRACE_INTERFACES = "APPTRACE_INTERFACES="; 737c478bd9Sstevel@tonic-gate static char const *APPTRACE_INTERFACES_EXCLUDE = "APPTRACE_INTERFACES_EXCLUDE="; 747c478bd9Sstevel@tonic-gate static char const *APPTRACE_VERBOSE = "APPTRACE_VERBOSE="; 757c478bd9Sstevel@tonic-gate static char const *APPTRACE_VERBOSE_EXCLUDE = "APPTRACE_VERBOSE_EXCLUDE="; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* Some default values for the above */ 787c478bd9Sstevel@tonic-gate static char *LD_AUDIT = "LD_AUDIT=/usr/lib/abi/apptrace.so.1"; 797c478bd9Sstevel@tonic-gate #if defined(sparc) || defined(__sparcv9) 807c478bd9Sstevel@tonic-gate static char *LD_AUDIT_64 = 817c478bd9Sstevel@tonic-gate "LD_AUDIT_64=/usr/lib/abi/sparcv9/apptrace.so.1"; 827c478bd9Sstevel@tonic-gate #elif defined(i386) || defined(__amd64) 837c478bd9Sstevel@tonic-gate static char *LD_AUDIT_64 = 847c478bd9Sstevel@tonic-gate "LD_AUDIT_64=/usr/lib/abi/amd64/apptrace.so.1"; 857c478bd9Sstevel@tonic-gate #else 867c478bd9Sstevel@tonic-gate #error Unsupported Platform 877c478bd9Sstevel@tonic-gate #endif 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static char const *one = "1"; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* The local support functions */ 927c478bd9Sstevel@tonic-gate static void usage(char const *); 937c478bd9Sstevel@tonic-gate static void stuffenv(char const *, char const *); 947c478bd9Sstevel@tonic-gate static char *buildlist(char **, char const *); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate int 977c478bd9Sstevel@tonic-gate main(int argc, char **argv) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate int opt; 1007c478bd9Sstevel@tonic-gate int fflag = FALSE; 1017c478bd9Sstevel@tonic-gate int errflg = FALSE; 1027c478bd9Sstevel@tonic-gate char *outfile = NULL; 1037c478bd9Sstevel@tonic-gate int stat_loc; 1047c478bd9Sstevel@tonic-gate pid_t wret, pid; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1077c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 1087c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 1097c478bd9Sstevel@tonic-gate #endif 1107c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* Squirrel the basename of the command name away. */ 1147c478bd9Sstevel@tonic-gate if ((command = strrchr(argv[0], '/')) != NULL) 1157c478bd9Sstevel@tonic-gate command++; 1167c478bd9Sstevel@tonic-gate else 1177c478bd9Sstevel@tonic-gate command = argv[0]; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, optlet)) != EOF) { 1207c478bd9Sstevel@tonic-gate switch (opt) { 1217c478bd9Sstevel@tonic-gate case 'F': 1227c478bd9Sstevel@tonic-gate if (*optarg == '!') 1237c478bd9Sstevel@tonic-gate (void) buildlist(&fromexcl, optarg + 1); 1247c478bd9Sstevel@tonic-gate else 1257c478bd9Sstevel@tonic-gate (void) buildlist(&fromlist, optarg); 1267c478bd9Sstevel@tonic-gate break; 1277c478bd9Sstevel@tonic-gate case 'f': 1287c478bd9Sstevel@tonic-gate fflag = TRUE; 1297c478bd9Sstevel@tonic-gate break; 1307c478bd9Sstevel@tonic-gate case 'o': 1317c478bd9Sstevel@tonic-gate outfile = optarg; 1327c478bd9Sstevel@tonic-gate break; 1337c478bd9Sstevel@tonic-gate case 'T': 1347c478bd9Sstevel@tonic-gate if (*optarg == '!') 1357c478bd9Sstevel@tonic-gate (void) buildlist(&toexcl, optarg + 1); 1367c478bd9Sstevel@tonic-gate else 1377c478bd9Sstevel@tonic-gate (void) buildlist(&tolist, optarg); 1387c478bd9Sstevel@tonic-gate break; 1397c478bd9Sstevel@tonic-gate case 't': 1407c478bd9Sstevel@tonic-gate if (*optarg == '!') 1417c478bd9Sstevel@tonic-gate (void) buildlist(&ifexcl, optarg + 1); 1427c478bd9Sstevel@tonic-gate else 1437c478bd9Sstevel@tonic-gate (void) buildlist(&iflist, optarg); 1447c478bd9Sstevel@tonic-gate break; 1457c478bd9Sstevel@tonic-gate case 'v': 1467c478bd9Sstevel@tonic-gate if (*optarg == '!') 1477c478bd9Sstevel@tonic-gate (void) buildlist(&vifexcl, optarg + 1); 1487c478bd9Sstevel@tonic-gate else 1497c478bd9Sstevel@tonic-gate (void) buildlist(&viflist, optarg); 1507c478bd9Sstevel@tonic-gate break; 1517c478bd9Sstevel@tonic-gate default: 1527c478bd9Sstevel@tonic-gate errflg = TRUE; 1537c478bd9Sstevel@tonic-gate break; 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Whack the argument vector so that the remainder will be 1597c478bd9Sstevel@tonic-gate * ready for passing to exec 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate argc -= optind; 1627c478bd9Sstevel@tonic-gate argv += optind; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * If there was a problem with the options, or there was no command 1667c478bd9Sstevel@tonic-gate * to be run, then give the usage message and bugout. 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate if (errflg || argc <= 0) { 1697c478bd9Sstevel@tonic-gate usage(command); 1707c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * This is where the environment gets setup. 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate if (fflag == TRUE) 1777c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_PID, one); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate if (fromexcl != NULL) 1807c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_BINDFROM_EXCLUDE, fromexcl); 1817c478bd9Sstevel@tonic-gate if (fromlist != NULL) 1827c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_BINDFROM, fromlist); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (tolist != NULL) 1857c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_BINDTO, tolist); 1867c478bd9Sstevel@tonic-gate if (toexcl != NULL) 1877c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_BINDTO_EXCLUDE, toexcl); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (iflist != NULL) 1907c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_INTERFACES, iflist); 1917c478bd9Sstevel@tonic-gate if (ifexcl != NULL) 1927c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_INTERFACES_EXCLUDE, ifexcl); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (viflist != NULL) 1957c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_VERBOSE, viflist); 1967c478bd9Sstevel@tonic-gate if (vifexcl != NULL) 1977c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_VERBOSE_EXCLUDE, vifexcl); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (outfile != NULL) 2007c478bd9Sstevel@tonic-gate stuffenv(APPTRACE_OUTPUT, outfile); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * It is the setting of the LD_AUDIT environment variable 2047c478bd9Sstevel@tonic-gate * that tells ld.so.1 to enable link auditing when the child 2057c478bd9Sstevel@tonic-gate * is exec()ed. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate (void) putenv(LD_AUDIT); 2087c478bd9Sstevel@tonic-gate (void) putenv(LD_AUDIT_64); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * The environment is now all setup. 2127c478bd9Sstevel@tonic-gate * For those about to rock, we salute you! 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate pid = fork(); 2157c478bd9Sstevel@tonic-gate switch (pid) { 2167c478bd9Sstevel@tonic-gate /* Error */ 2177c478bd9Sstevel@tonic-gate case -1: 2187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: fork failed: %s\n"), 2197c478bd9Sstevel@tonic-gate command, strerror(errno)); 2207c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 2217c478bd9Sstevel@tonic-gate break; 2227c478bd9Sstevel@tonic-gate /* Child */ 2237c478bd9Sstevel@tonic-gate case 0: 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Usual failure is argv[0] does not exist or is 2267c478bd9Sstevel@tonic-gate * not executable. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if (execvp(argv[0], argv)) { 2297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: %s: %s\n"), 2307c478bd9Sstevel@tonic-gate command, argv[0], strerror(errno)); 2317c478bd9Sstevel@tonic-gate _exit(EXIT_FAILURE); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate break; 2347c478bd9Sstevel@tonic-gate /* Parent */ 2357c478bd9Sstevel@tonic-gate default: 2367c478bd9Sstevel@tonic-gate wret = waitpid(pid, &stat_loc, 0); 2377c478bd9Sstevel@tonic-gate if (wret == -1) { 2387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2397c478bd9Sstevel@tonic-gate gettext("%s: waitpid failed: %s\n"), 2407c478bd9Sstevel@tonic-gate command, strerror(errno)); 2417c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (wret != pid) { 2457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2467c478bd9Sstevel@tonic-gate gettext("%s: " 2477c478bd9Sstevel@tonic-gate "waitpid returned %ld when child pid was %ld\n"), 2487c478bd9Sstevel@tonic-gate command, wret, pid); 2497c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (WIFSIGNALED(stat_loc)) { 2537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("\n%s: %s: %s"), 2547c478bd9Sstevel@tonic-gate command, argv[0], strsignal(WTERMSIG(stat_loc))); 2557c478bd9Sstevel@tonic-gate if (WCOREDUMP(stat_loc)) { 2567c478bd9Sstevel@tonic-gate (void) fputs(gettext("(Core dump)"), stderr); 2577c478bd9Sstevel@tonic-gate #ifdef DEBUG 2587c478bd9Sstevel@tonic-gate (void) fputs(gettext("\nRunning pstack:\n"), 2597c478bd9Sstevel@tonic-gate stderr); 2607c478bd9Sstevel@tonic-gate (void) putenv("LD_AUDIT="); 2617c478bd9Sstevel@tonic-gate (void) putenv("LD_AUDIT_64="); 2627c478bd9Sstevel@tonic-gate (void) system("/usr/proc/bin/pstack core"); 2637c478bd9Sstevel@tonic-gate #endif 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate (void) putc('\n', stderr); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /* Normal return from main() */ 2697c478bd9Sstevel@tonic-gate return (WEXITSTATUS(stat_loc)); 2707c478bd9Sstevel@tonic-gate } 271*f07a2a2eScraigm return (0); 2727c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * Take a string in the form "VAR=" and another in the 2777c478bd9Sstevel@tonic-gate * form "value" and paste them together. 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate static void 2807c478bd9Sstevel@tonic-gate stuffenv(char const *var, char const *val) 2817c478bd9Sstevel@tonic-gate { 2827c478bd9Sstevel@tonic-gate int lenvar, lenval; 2837c478bd9Sstevel@tonic-gate char *stuff; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate lenvar = strlen(var); 2867c478bd9Sstevel@tonic-gate lenval = strlen(val); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate if ((stuff = malloc(lenvar + lenval + 1)) == NULL) { 2897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: malloc failed\n"), command); 2907c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate (void) sprintf(stuff, "%s%s", var, val); 2937c478bd9Sstevel@tonic-gate (void) putenv(stuff); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * If *dst is empty, use strdup to duplicate src. 2987c478bd9Sstevel@tonic-gate * Otherwise: dst = dst + "," + src; 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate static char * 3017c478bd9Sstevel@tonic-gate buildlist(char **dst, char const *src) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate int len; 3047c478bd9Sstevel@tonic-gate char *p; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * If dst is still empty then dup, 3087c478bd9Sstevel@tonic-gate * if dup succeeds set dst. 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate if (*dst == NULL) { 3117c478bd9Sstevel@tonic-gate p = strdup(src); 3127c478bd9Sstevel@tonic-gate if (p == NULL) 3137c478bd9Sstevel@tonic-gate goto error; 3147c478bd9Sstevel@tonic-gate *dst = p; 3157c478bd9Sstevel@tonic-gate return (p); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate len = strlen(*dst); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* +2 because of the comma we add below */ 3217c478bd9Sstevel@tonic-gate if ((p = realloc(*dst, len + strlen(src) + 2)) == NULL) 3227c478bd9Sstevel@tonic-gate goto error; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate *dst = p; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate *(*dst + len) = ','; 3277c478bd9Sstevel@tonic-gate (void) strcpy((*dst + len + 1), src); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate return (*dst); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate error: 3327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: allocation failed: %s\n"), 3337c478bd9Sstevel@tonic-gate command, strerror(errno)); 3347c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 3357c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate static void 3397c478bd9Sstevel@tonic-gate usage(char const *prog) 3407c478bd9Sstevel@tonic-gate { 3417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage: %s [-f][-F [!]tracefromlist]" 3427c478bd9Sstevel@tonic-gate "[-T [!]tracetolist][-o outputfile]\n" 3437c478bd9Sstevel@tonic-gate " [-t calls][-v calls] prog [prog arguments]\n" 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate " -F <bindfromlist>\n" 3467c478bd9Sstevel@tonic-gate " A comma separated list of libraries that are to be\n" 3477c478bd9Sstevel@tonic-gate " traced. Only calls from these libraries will be\n" 3487c478bd9Sstevel@tonic-gate " traced. The default is to trace calls from the\n" 3497c478bd9Sstevel@tonic-gate " main executable.\n" 3507c478bd9Sstevel@tonic-gate " If <bindfromlist> begins with a ! then it defines\n" 3517c478bd9Sstevel@tonic-gate " a list of libraries to exclude from the trace.\n" 3527c478bd9Sstevel@tonic-gate " -T <bindtolist>\n" 3537c478bd9Sstevel@tonic-gate " A comma separated list of libraries that are to be\n" 3547c478bd9Sstevel@tonic-gate " traced. Only calls to these libraries will be\n" 3557c478bd9Sstevel@tonic-gate " traced. The default is to trace all calls.\n" 3567c478bd9Sstevel@tonic-gate " If <bindtolist> begins with a ! then it defines\n" 3577c478bd9Sstevel@tonic-gate " a list of libraries to exclude from the trace.\n" 3587c478bd9Sstevel@tonic-gate " -o <outputfile>\n" 3597c478bd9Sstevel@tonic-gate " %s output will be directed to 'outputfile'.\n" 3607c478bd9Sstevel@tonic-gate " by default it is placed on stderr\n" 3617c478bd9Sstevel@tonic-gate " -f\n" 3627c478bd9Sstevel@tonic-gate " Follow all children created by fork() and also\n" 3637c478bd9Sstevel@tonic-gate " print apptrace output for the children. This also\n" 3647c478bd9Sstevel@tonic-gate " causes a 'pid' to be added to each output line\n" 3657c478bd9Sstevel@tonic-gate " -t <tracelist>\n" 3667c478bd9Sstevel@tonic-gate " A comma separated list of interfaces to trace.\n" 3677c478bd9Sstevel@tonic-gate " A list preceded by ! is an exlusion list.\n" 3687c478bd9Sstevel@tonic-gate " -v <verboselist>\n" 3697c478bd9Sstevel@tonic-gate " A comman separated list of interfaces to trace\n" 3707c478bd9Sstevel@tonic-gate " verbosely.\n" 3717c478bd9Sstevel@tonic-gate " A list preceded by ! is an exclusion list.\n" 3727c478bd9Sstevel@tonic-gate " Interfaces matched in -v do not also need to be\n" 3737c478bd9Sstevel@tonic-gate " named by -t\n" 3747c478bd9Sstevel@tonic-gate " All lists may use shell style wild cards.\n" 3757c478bd9Sstevel@tonic-gate " Leading path components or suffixes are not required when\n" 3767c478bd9Sstevel@tonic-gate " listing libraries (ie. libc will match /usr/lib/libc.so.1).\n"), 3777c478bd9Sstevel@tonic-gate prog, prog); 3787c478bd9Sstevel@tonic-gate } 379