xref: /titanic_51/usr/src/cmd/tnf/prex/main.c (revision c5024742c2f7d10880eae26cc592353b20a58f4a)
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
5*c5024742Srab  * Common Development and Distribution License (the "License").
6*c5024742Srab  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*c5024742Srab  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Includes
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <stdio.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <signal.h>
377c478bd9Sstevel@tonic-gate #include <errno.h>
387c478bd9Sstevel@tonic-gate #include <locale.h>
397c478bd9Sstevel@tonic-gate #include <libintl.h>
407c478bd9Sstevel@tonic-gate #include <fcntl.h>
417c478bd9Sstevel@tonic-gate #include <limits.h>
427c478bd9Sstevel@tonic-gate #include <sys/stat.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/param.h>
457c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
467c478bd9Sstevel@tonic-gate #include <libelf.h>
477c478bd9Sstevel@tonic-gate #include <gelf.h>
487c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <tnf/tnfctl.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #include "set.h"
537c478bd9Sstevel@tonic-gate #include "cmd.h"
547c478bd9Sstevel@tonic-gate #include "spec.h"
557c478bd9Sstevel@tonic-gate #include "expr.h"
567c478bd9Sstevel@tonic-gate #include "source.h"
577c478bd9Sstevel@tonic-gate #include "list.h"
587c478bd9Sstevel@tonic-gate #include "prbk.h"
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * Defines - Project private interfaces
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #define	DEBUG_ENTRY		"tnf_probe_debug"
657c478bd9Sstevel@tonic-gate #ifdef TESTING
667c478bd9Sstevel@tonic-gate #define	EMPTY_ENTRY		"tnf_probe_empty"
677c478bd9Sstevel@tonic-gate #endif
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	USER_OUTSIZE		(4*1024*1024)
707c478bd9Sstevel@tonic-gate #define	KERNEL_OUTSIZE		(384*1024)
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #if defined(__sparc)
737c478bd9Sstevel@tonic-gate #define	PREX32DIR	"/sparcv7/"
747c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64)
757c478bd9Sstevel@tonic-gate #define	PREX32DIR	"/i86/"
767c478bd9Sstevel@tonic-gate #endif
777c478bd9Sstevel@tonic-gate #define	PREX32EXEC	"/usr/bin" PREX32DIR "prex"
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * Globals
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate char			**g_argv;	/* copy of argv pointer */
847c478bd9Sstevel@tonic-gate tnfctl_handle_t		*g_hndl;	/* handle on target or kernel */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static int		g_verbose;	/* debugging to stderr */
877c478bd9Sstevel@tonic-gate static char		*g_cmdname;	/* target command name */
887c478bd9Sstevel@tonic-gate static char		**g_cmdargs;	/* target command args */
897c478bd9Sstevel@tonic-gate static pid_t		g_targetpid;	/* target process id */
907c478bd9Sstevel@tonic-gate static volatile boolean_t g_getcmds;	/* accept input flag */
917c478bd9Sstevel@tonic-gate static boolean_t	g_testflag;	/* asserted in test mode */
927c478bd9Sstevel@tonic-gate static char		*g_preload;	/* objects to preload */
937c478bd9Sstevel@tonic-gate static char		*g_outname;	/* tracefile name */
947c478bd9Sstevel@tonic-gate static char		*tracefile;	/* tracefile name used by list cmd */
957c478bd9Sstevel@tonic-gate int			g_outsize;	/* tracefile size */
967c478bd9Sstevel@tonic-gate boolean_t		g_kernelmode;	/* -k flag: kernel mode */
977c478bd9Sstevel@tonic-gate static int		prex_dmodel;	/* prex data model */
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * Local Declarations
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate static void usage(char **argv, const char *msg);
1037c478bd9Sstevel@tonic-gate static void scanargs(int argc, char **argv);
1047c478bd9Sstevel@tonic-gate static int set_signal(void);
1057c478bd9Sstevel@tonic-gate static int get_data_model(pid_t pid);
1067c478bd9Sstevel@tonic-gate static int get_elf_class(char *filename);
1077c478bd9Sstevel@tonic-gate static int get_executable(char *);
1087c478bd9Sstevel@tonic-gate static void prex_isaexec(char **argv, char **envp);
1097c478bd9Sstevel@tonic-gate static void check_pid_model(char **argv, char **envp);
1107c478bd9Sstevel@tonic-gate static void check_exec_model(char **argv, char **envp);
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /* #### - FIXME - need to put this in a private header file */
1137c478bd9Sstevel@tonic-gate extern void err_fatal(char *s, ...);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate extern int	  yyparse(void);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate static tnfctl_errcode_t check_trace_error(tnfctl_handle_t *hndl);
1187c478bd9Sstevel@tonic-gate static void set_default_cmd(void);
1197c478bd9Sstevel@tonic-gate static void get_commands(void);
1207c478bd9Sstevel@tonic-gate static tnfctl_errcode_t set_tracefile(tnfctl_handle_t *hndl);
1217c478bd9Sstevel@tonic-gate static tnfctl_errcode_t set_probe_discovery_callback(tnfctl_handle_t *hndl);
1227c478bd9Sstevel@tonic-gate static void * perprobe(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_p);
1237c478bd9Sstevel@tonic-gate static tnfctl_errcode_t perprobe2(tnfctl_handle_t *hndl,
1247c478bd9Sstevel@tonic-gate 	tnfctl_probe_t *probe_p, void *ignored);
1257c478bd9Sstevel@tonic-gate static tnfctl_errcode_t percmd(expr_t *expr_p, cmd_kind_t kind, fcn_t *fcn_p,
1267c478bd9Sstevel@tonic-gate 	boolean_t isnew, void *calldata_p);
1277c478bd9Sstevel@tonic-gate void quit(boolean_t killtarget, boolean_t runtarget);
1287c478bd9Sstevel@tonic-gate void cmd_listtracefile();
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * usage() - gives a description of the arguments, and exits
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate static void
1367c478bd9Sstevel@tonic-gate usage(char *argv[], const char *msg)
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	if (msg)
1397c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1407c478bd9Sstevel@tonic-gate 			gettext("%s: %s\n"), argv[0], msg);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1437c478bd9Sstevel@tonic-gate 		"usage: %s [options] <cmd> [cmd-args...]\n"), argv[0]);
1447c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1457c478bd9Sstevel@tonic-gate 		"usage: %s [options] -p <pid>\n"), argv[0]);
1467c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1477c478bd9Sstevel@tonic-gate 		"usage: %s -s <kbytes-size> -k\n"), argv[0]);
1487c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1497c478bd9Sstevel@tonic-gate 		"options:\n"));
1507c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1517c478bd9Sstevel@tonic-gate 		"	-o <outfilename>   set trace output file name\n"));
1527c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1537c478bd9Sstevel@tonic-gate 		"	-s <kbytes-size>   set trace file size\n"));
1547c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
1557c478bd9Sstevel@tonic-gate 		"	-l <sharedobjs>    shared objects to "
1567c478bd9Sstevel@tonic-gate 		"be preloaded (cmd only)\n"));
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	exit(1);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate  * main() -
1647c478bd9Sstevel@tonic-gate  */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate int
1677c478bd9Sstevel@tonic-gate main(int argc, char **argv, char **envp)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	err = TNFCTL_ERR_NONE;
1707c478bd9Sstevel@tonic-gate 	int			sys_err;
1717c478bd9Sstevel@tonic-gate 	tnfctl_trace_attrs_t	trace_attrs;
1727c478bd9Sstevel@tonic-gate 	tnfctl_event_t		event = TNFCTL_EVENT_EINTR;
1737c478bd9Sstevel@tonic-gate 	pid_t			prex_pid;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/* internationalization stuff */
1767c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1777c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
1787c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
1797c478bd9Sstevel@tonic-gate #endif
1807c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	g_argv = argv;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	prex_pid = getpid();
1857c478bd9Sstevel@tonic-gate #if defined(DEBUG)
1867c478bd9Sstevel@tonic-gate 	fprintf(stderr, "### prex_pid = %d ###\n", prex_pid);
1877c478bd9Sstevel@tonic-gate #endif
1887c478bd9Sstevel@tonic-gate 	prex_dmodel = get_data_model(prex_pid);
1897c478bd9Sstevel@tonic-gate #if defined(DEBUG)
1907c478bd9Sstevel@tonic-gate 	fprintf(stderr, "### prex_dmodel = %d ###\n", prex_dmodel);
1917c478bd9Sstevel@tonic-gate #endif
1927c478bd9Sstevel@tonic-gate 	scanargs(argc, argv);
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
1957c478bd9Sstevel@tonic-gate 		/* prexing the kernel */
1967c478bd9Sstevel@tonic-gate 		err = tnfctl_kernel_open(&g_hndl);
1977c478bd9Sstevel@tonic-gate 		if (err) {
1987c478bd9Sstevel@tonic-gate 			err_fatal(gettext(
1997c478bd9Sstevel@tonic-gate 				"%s: trouble attaching to the kernel: %s\n"),
2007c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
2017c478bd9Sstevel@tonic-gate 		}
2027c478bd9Sstevel@tonic-gate 	} else {
2037c478bd9Sstevel@tonic-gate 		/* prexing a user process */
2047c478bd9Sstevel@tonic-gate 		if (g_targetpid != 0) {
2057c478bd9Sstevel@tonic-gate 			/* check data model */
2067c478bd9Sstevel@tonic-gate 			check_pid_model(argv, envp);
2077c478bd9Sstevel@tonic-gate 			/* attach case */
2087c478bd9Sstevel@tonic-gate 			err = tnfctl_pid_open(g_targetpid, &g_hndl);
2097c478bd9Sstevel@tonic-gate 			if (err == TNFCTL_ERR_NOLIBTNFPROBE) {
2107c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
2117c478bd9Sstevel@tonic-gate 					"%s: missing symbols, is "
2127c478bd9Sstevel@tonic-gate 					"libtnfprobe.so loaded in target?\n"),
2137c478bd9Sstevel@tonic-gate 					argv[0], tnfctl_strerror(err));
2147c478bd9Sstevel@tonic-gate 			} else if (err) {
2157c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
2167c478bd9Sstevel@tonic-gate 					"%s: trouble attaching to target "
2177c478bd9Sstevel@tonic-gate 					"process: %s\n"),
2187c478bd9Sstevel@tonic-gate 					argv[0], tnfctl_strerror(err));
2197c478bd9Sstevel@tonic-gate 			}
2207c478bd9Sstevel@tonic-gate 		} else {
2217c478bd9Sstevel@tonic-gate 			/* check elf class model */
2227c478bd9Sstevel@tonic-gate 			check_exec_model(argv, envp);
2237c478bd9Sstevel@tonic-gate 			/* exec case */
2247c478bd9Sstevel@tonic-gate 			err = tnfctl_exec_open(g_cmdname, g_cmdargs, NULL,
2257c478bd9Sstevel@tonic-gate 					g_preload, NULL, &g_hndl);
2267c478bd9Sstevel@tonic-gate 			if (err == TNFCTL_ERR_NONE)
2277c478bd9Sstevel@tonic-gate 				err = tnfctl_trace_attrs_get(g_hndl,
2287c478bd9Sstevel@tonic-gate 						&trace_attrs);
2297c478bd9Sstevel@tonic-gate 			if (err) {
2307c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
2317c478bd9Sstevel@tonic-gate 					"%s: trouble creating target process: "
2327c478bd9Sstevel@tonic-gate 					"%s\n"),
2337c478bd9Sstevel@tonic-gate 					argv[0], tnfctl_strerror(err));
2347c478bd9Sstevel@tonic-gate 			}
2357c478bd9Sstevel@tonic-gate 			g_targetpid = trace_attrs.targ_pid;
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 		sys_err = set_signal();
2397c478bd9Sstevel@tonic-gate 		if (sys_err)
2407c478bd9Sstevel@tonic-gate 			err_fatal(gettext(
2417c478bd9Sstevel@tonic-gate 				"%s: trouble setting up signal handler: %s\n"),
2427c478bd9Sstevel@tonic-gate 				argv[0], strerror(err));
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	/* initialize the source stack for the parser */
2467c478bd9Sstevel@tonic-gate 	source_init();
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	if (!g_kernelmode) {
2497c478bd9Sstevel@tonic-gate 		/* set the tracefile name and size */
2507c478bd9Sstevel@tonic-gate 		err = set_tracefile(g_hndl);
2517c478bd9Sstevel@tonic-gate 		if (err) {
2527c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
2537c478bd9Sstevel@tonic-gate 				"%s: trouble initializing tracefile: %s\n"),
2547c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
2557c478bd9Sstevel@tonic-gate 			goto Cleanup;
2567c478bd9Sstevel@tonic-gate 		}
2577c478bd9Sstevel@tonic-gate 		err = check_trace_error(g_hndl);
2587c478bd9Sstevel@tonic-gate 		if (err) {
2597c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
2607c478bd9Sstevel@tonic-gate 				"%s: cannot read tracing status : %s\n"),
2617c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
2627c478bd9Sstevel@tonic-gate 			goto Cleanup;
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	/* accept commands from stdin the first time through */
2677c478bd9Sstevel@tonic-gate 	g_getcmds = B_TRUE;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	/* set up default aliases */
2707c478bd9Sstevel@tonic-gate 	set_default_cmd();
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	/* set up creator/destructor function to call for new probes */
2737c478bd9Sstevel@tonic-gate 	err = set_probe_discovery_callback(g_hndl);
2747c478bd9Sstevel@tonic-gate 	if (err) {
2757c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
2767c478bd9Sstevel@tonic-gate 			"%s: error in probe discovery : %s\n"),
2777c478bd9Sstevel@tonic-gate 			argv[0], tnfctl_strerror(err));
2787c478bd9Sstevel@tonic-gate 		goto Cleanup;
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
2827c478bd9Sstevel@tonic-gate 		prbk_warn_pfilter_empty();
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	while (err == TNFCTL_ERR_NONE) {
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		if (g_kernelmode || g_getcmds) {
2887c478bd9Sstevel@tonic-gate 			g_getcmds = B_FALSE;
2897c478bd9Sstevel@tonic-gate 			get_commands();
2907c478bd9Sstevel@tonic-gate 		}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 		if (!g_kernelmode && (g_getcmds == B_FALSE)) {
2937c478bd9Sstevel@tonic-gate 		    err = tnfctl_continue(g_hndl, &event, NULL);
2947c478bd9Sstevel@tonic-gate 		    if (err) {
2957c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
2967c478bd9Sstevel@tonic-gate 				"%s: cannot continue target : %s\n"),
2977c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
2987c478bd9Sstevel@tonic-gate 			goto Cleanup;
2997c478bd9Sstevel@tonic-gate 		    }
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		err = check_trace_error(g_hndl);
3027c478bd9Sstevel@tonic-gate 		if (err) {
3037c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
3047c478bd9Sstevel@tonic-gate 				"%s: cannot read tracing status : %s\n"),
3057c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
3067c478bd9Sstevel@tonic-gate 			goto Cleanup;
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate 		if (!g_kernelmode) {
3097c478bd9Sstevel@tonic-gate 			if (event == TNFCTL_EVENT_EXEC) {
3107c478bd9Sstevel@tonic-gate 			    (void) printf(gettext(
3117c478bd9Sstevel@tonic-gate 				"Target process exec'd\n"));
3127c478bd9Sstevel@tonic-gate 			    quit(B_FALSE, B_TRUE);	/* quit resume */
3137c478bd9Sstevel@tonic-gate 			} else if (event == TNFCTL_EVENT_EXIT) {
3147c478bd9Sstevel@tonic-gate 			    /* target exited */
3157c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr, gettext(
3167c478bd9Sstevel@tonic-gate 				"%s: target process exited\n"),
3177c478bd9Sstevel@tonic-gate 				g_argv[0]);
3187c478bd9Sstevel@tonic-gate 			    goto Cleanup;
3197c478bd9Sstevel@tonic-gate 			} else if (event == TNFCTL_EVENT_TARGGONE) {
3207c478bd9Sstevel@tonic-gate 				/* target terminated */
3217c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
3227c478bd9Sstevel@tonic-gate 	gettext("%s: target process disappeared (without calling exit)\n"),
3237c478bd9Sstevel@tonic-gate 				g_argv[0]);
3247c478bd9Sstevel@tonic-gate 			    goto Cleanup;
3257c478bd9Sstevel@tonic-gate 			}
3267c478bd9Sstevel@tonic-gate 		}
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate Cleanup:
3307c478bd9Sstevel@tonic-gate 	err = tnfctl_close(g_hndl, TNFCTL_TARG_DEFAULT);
3317c478bd9Sstevel@tonic-gate 	if (err)
3327c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
3337c478bd9Sstevel@tonic-gate 			"%s: error on closing : %s\n"),
3347c478bd9Sstevel@tonic-gate 			argv[0], tnfctl_strerror(err));
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	exit(0);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	return (0);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate  * check_trace_error() - checks whether there was an error in tracing
3447c478bd9Sstevel@tonic-gate  */
3457c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
3467c478bd9Sstevel@tonic-gate check_trace_error(tnfctl_handle_t *hndl)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	tnfctl_trace_attrs_t	trace_attrs;
3497c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	err;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	err = tnfctl_trace_attrs_get(hndl, &trace_attrs);
3527c478bd9Sstevel@tonic-gate 	if (err)
3537c478bd9Sstevel@tonic-gate 		return (err);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	if (trace_attrs.trace_buf_state == TNFCTL_BUF_BROKEN) {
3567c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Tracing shut down in target program "
3577c478bd9Sstevel@tonic-gate 			"due to an internal error - Please restart prex "
3587c478bd9Sstevel@tonic-gate 			"and target\n"));
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate /*
3657c478bd9Sstevel@tonic-gate  * set_default_cmd() - set the default debug entry and $all
3667c478bd9Sstevel@tonic-gate  */
3677c478bd9Sstevel@tonic-gate static void
3687c478bd9Sstevel@tonic-gate set_default_cmd(void)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate 	if (!g_kernelmode)
3717c478bd9Sstevel@tonic-gate 		fcn(strdup("debug"), DEBUG_ENTRY);
3727c478bd9Sstevel@tonic-gate #ifdef TESTING
3737c478bd9Sstevel@tonic-gate 	fcn(strdup("empty"), EMPTY_ENTRY);
3747c478bd9Sstevel@tonic-gate #endif
3757c478bd9Sstevel@tonic-gate 	(void) set(strdup("all"), expr(spec(strdup("keys"), SPEC_EXACT),
3767c478bd9Sstevel@tonic-gate 				spec(strdup(".*"), SPEC_REGEXP)));
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate /*
3817c478bd9Sstevel@tonic-gate  * process() - enable and disable selected probes
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate typedef struct {
3857c478bd9Sstevel@tonic-gate 	tnfctl_probe_t	*probe_p;
3867c478bd9Sstevel@tonic-gate 	tnfctl_handle_t	*hndl;
3877c478bd9Sstevel@tonic-gate } process_args_t;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
3907c478bd9Sstevel@tonic-gate percmd(expr_t *expr_p, cmd_kind_t kind, fcn_t *fcn_p, boolean_t isnew,
3917c478bd9Sstevel@tonic-gate 	void *calldata_p)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	process_args_t *args_p = (process_args_t *)calldata_p;
3947c478bd9Sstevel@tonic-gate 	tnfctl_handle_t	*hndl = args_p->hndl;
3957c478bd9Sstevel@tonic-gate 	tnfctl_probe_t	*probe_p = args_p->probe_p;
3967c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err = TNFCTL_ERR_NONE;
3977c478bd9Sstevel@tonic-gate 	char *attrs;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	attrs = list_getattrs(probe_p);
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if (expr_match(expr_p, attrs)) {
4027c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
4037c478bd9Sstevel@tonic-gate 		if (g_verbose) {
4047c478bd9Sstevel@tonic-gate 			char		   *cmdstr[] = {
4057c478bd9Sstevel@tonic-gate 				"enable", "disable",
4067c478bd9Sstevel@tonic-gate 				"connect", "clear",
4077c478bd9Sstevel@tonic-gate 				"trace", "untrace"};
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, ": %s command: %s ",
4107c478bd9Sstevel@tonic-gate 				(isnew) ? "new" : "old", cmdstr[kind]);
4117c478bd9Sstevel@tonic-gate 			expr_print(stderr, expr_p);
4127c478bd9Sstevel@tonic-gate 		}
4137c478bd9Sstevel@tonic-gate #endif
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 		switch (kind) {
4167c478bd9Sstevel@tonic-gate 		case CMD_ENABLE:
4177c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_enable(hndl, probe_p, NULL);
4187c478bd9Sstevel@tonic-gate 			break;
4197c478bd9Sstevel@tonic-gate 		case CMD_DISABLE:
4207c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_disable(hndl, probe_p, NULL);
4217c478bd9Sstevel@tonic-gate 			break;
4227c478bd9Sstevel@tonic-gate 		case CMD_TRACE:
4237c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_trace(hndl, probe_p, NULL);
4247c478bd9Sstevel@tonic-gate 			break;
4257c478bd9Sstevel@tonic-gate 		case CMD_UNTRACE:
4267c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_untrace(hndl, probe_p, NULL);
4277c478bd9Sstevel@tonic-gate 			break;
4287c478bd9Sstevel@tonic-gate 		case CMD_CONNECT:
4297c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_connect(hndl, probe_p, NULL,
4307c478bd9Sstevel@tonic-gate 				fcn_p->entry_name_p);
4317c478bd9Sstevel@tonic-gate 			break;
4327c478bd9Sstevel@tonic-gate 		case CMD_CLEAR:
4337c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_disconnect_all(hndl, probe_p, NULL);
4347c478bd9Sstevel@tonic-gate 			break;
4357c478bd9Sstevel@tonic-gate 		}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
4387c478bd9Sstevel@tonic-gate 		if (g_verbose)
4397c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\n");
4407c478bd9Sstevel@tonic-gate #endif
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 	if (attrs)
4447c478bd9Sstevel@tonic-gate 		free(attrs);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	return (err);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4517c478bd9Sstevel@tonic-gate static void *
4527c478bd9Sstevel@tonic-gate perprobe(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_p)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate 	process_args_t  args;
4557c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	args.probe_p = probe_p;
4587c478bd9Sstevel@tonic-gate 	args.hndl = hndl;
4597c478bd9Sstevel@tonic-gate 	err = cmd_traverse(percmd, &args);
4607c478bd9Sstevel@tonic-gate 	if (err) {
4617c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
4627c478bd9Sstevel@tonic-gate 				"%s: error on new (dlopened) probe : %s\n"),
4637c478bd9Sstevel@tonic-gate 				g_argv[0], tnfctl_strerror(err));
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 	return (NULL);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
4697c478bd9Sstevel@tonic-gate set_probe_discovery_callback(tnfctl_handle_t *hndl)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	err = tnfctl_register_funcs(hndl, perprobe, NULL);
4747c478bd9Sstevel@tonic-gate 	if (err)
4757c478bd9Sstevel@tonic-gate 		return (err);
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
4817c478bd9Sstevel@tonic-gate perprobe2(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_p, void *cd)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate 	cmd_t		*cmd = cd;
4847c478bd9Sstevel@tonic-gate 	process_args_t  args;
4857c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	args.probe_p = probe_p;
4887c478bd9Sstevel@tonic-gate 	args.hndl = hndl;
4897c478bd9Sstevel@tonic-gate 	err = cmd_callback(cmd, percmd, &args);
4907c478bd9Sstevel@tonic-gate 	if (err) {
4917c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
4927c478bd9Sstevel@tonic-gate 				"%s: error on probe operation: %s\n"),
4937c478bd9Sstevel@tonic-gate 				g_argv[0], tnfctl_strerror(err));
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 	return (err);
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate void
4997c478bd9Sstevel@tonic-gate process_cmd(tnfctl_handle_t *hndl, cmd_t *cmd)
5007c478bd9Sstevel@tonic-gate {
5017c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
5027c478bd9Sstevel@tonic-gate 	if (g_verbose)
5037c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "processing commands\n");
5047c478bd9Sstevel@tonic-gate #endif
5057c478bd9Sstevel@tonic-gate 	(void) tnfctl_probe_apply(hndl, perprobe2, cmd);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate  * get_commands() - process commands from stdin
5107c478bd9Sstevel@tonic-gate  */
5117c478bd9Sstevel@tonic-gate static void
5127c478bd9Sstevel@tonic-gate get_commands(void)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate 	/* Read commands from STDIN */
5157c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
5167c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Type \"help\" for help ...\n"));
5177c478bd9Sstevel@tonic-gate 	} else {
5187c478bd9Sstevel@tonic-gate 		if (g_testflag)
5197c478bd9Sstevel@tonic-gate 			(void) printf("prex(%ld), target(%ld): ",
5207c478bd9Sstevel@tonic-gate 					getpid(), g_targetpid);
5217c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Target process stopped\n"));
5227c478bd9Sstevel@tonic-gate 		(void) printf(gettext(
5237c478bd9Sstevel@tonic-gate 			"Type \"continue\" to resume the target, "
5247c478bd9Sstevel@tonic-gate 			"\"help\" for help ...\n"));
5257c478bd9Sstevel@tonic-gate 	}
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	while (yyparse());
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate  * quit() - called to quit the controlling process. The boolean argument
5337c478bd9Sstevel@tonic-gate  * specifies whether to terminate the target as well.
5347c478bd9Sstevel@tonic-gate  */
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate void
5377c478bd9Sstevel@tonic-gate quit(boolean_t killtarget, boolean_t runtarget)
5387c478bd9Sstevel@tonic-gate {
5397c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (killtarget && runtarget)
5427c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_DEFAULT);
5437c478bd9Sstevel@tonic-gate 	else if (killtarget && !runtarget)
5447c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_KILL);
5457c478bd9Sstevel@tonic-gate 	else if (!killtarget && runtarget)
5467c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_RESUME);
5477c478bd9Sstevel@tonic-gate 	else if (!killtarget && !runtarget)
5487c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_SUSPEND);
5497c478bd9Sstevel@tonic-gate 	if (err) {
5507c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
5517c478bd9Sstevel@tonic-gate 				"%s: trouble quitting : %s\n"),
5527c478bd9Sstevel@tonic-gate 				g_argv[0], tnfctl_strerror(err));
5537c478bd9Sstevel@tonic-gate 		exit(1);
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 	exit(0);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate  * scanargs() - processes the command line arguments
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate #define	strneq(s1, s2, n) 	(strncmp(s1, s2, n) == 0)
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate static void
5667c478bd9Sstevel@tonic-gate scanargs(int argc,
5677c478bd9Sstevel@tonic-gate 	char **argv)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate 	int			 c;
5707c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
5717c478bd9Sstevel@tonic-gate 	char		   *optstr = "l:o:p:s:tkv:";	/* debugging options */
5727c478bd9Sstevel@tonic-gate #else
5737c478bd9Sstevel@tonic-gate 	char		   *optstr = "l:o:p:s:tk";	/* production options */
5747c478bd9Sstevel@tonic-gate #endif
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	/* set up some defaults */
5777c478bd9Sstevel@tonic-gate 	g_targetpid = 0;
5787c478bd9Sstevel@tonic-gate 	g_cmdname = NULL;
5797c478bd9Sstevel@tonic-gate 	g_cmdargs = NULL;
5807c478bd9Sstevel@tonic-gate 	g_preload = NULL;
5817c478bd9Sstevel@tonic-gate 	g_outname = NULL;
5827c478bd9Sstevel@tonic-gate 	g_outsize = -1;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, optstr)) != EOF) {
5857c478bd9Sstevel@tonic-gate 		switch (c) {
5867c478bd9Sstevel@tonic-gate 		case 'l':	/* preload objects */
5877c478bd9Sstevel@tonic-gate 			g_preload = optarg;
5887c478bd9Sstevel@tonic-gate 			break;
5897c478bd9Sstevel@tonic-gate 		case 'o':	/* tracefile name */
5907c478bd9Sstevel@tonic-gate 			g_outname = optarg;
5917c478bd9Sstevel@tonic-gate 			break;
5927c478bd9Sstevel@tonic-gate 		case 'p':	/* target pid (attach case) */
5937c478bd9Sstevel@tonic-gate 			g_targetpid = atoi(optarg);
5947c478bd9Sstevel@tonic-gate 			break;
5957c478bd9Sstevel@tonic-gate 		case 's':	/* tracefile size */
5967c478bd9Sstevel@tonic-gate 			g_outsize = atoi(optarg) * 1024;
5977c478bd9Sstevel@tonic-gate 			break;
5987c478bd9Sstevel@tonic-gate 		case 't':	/* test flag */
5997c478bd9Sstevel@tonic-gate 			g_testflag = B_TRUE;
6007c478bd9Sstevel@tonic-gate 			(void) setvbuf(stdout, NULL, _IOLBF, 0);
6017c478bd9Sstevel@tonic-gate 			break;
6027c478bd9Sstevel@tonic-gate 		case 'k':	/* kernel mode */
6037c478bd9Sstevel@tonic-gate 			g_kernelmode = B_TRUE;
6047c478bd9Sstevel@tonic-gate 			break;
6057c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
6067c478bd9Sstevel@tonic-gate 		case 'v':	/* verbose flag */
6077c478bd9Sstevel@tonic-gate 			g_verbose = atoi(optarg);
6087c478bd9Sstevel@tonic-gate 			break;
6097c478bd9Sstevel@tonic-gate #endif
6107c478bd9Sstevel@tonic-gate 		case '?':	/* error case */
6117c478bd9Sstevel@tonic-gate 			usage(argv, gettext("unrecognized argument"));
6127c478bd9Sstevel@tonic-gate 		}
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	if (optind < argc) {
6167c478bd9Sstevel@tonic-gate 		g_cmdname = strdup(argv[optind]);
6177c478bd9Sstevel@tonic-gate 		g_cmdargs = &argv[optind];
6187c478bd9Sstevel@tonic-gate 	}
6197c478bd9Sstevel@tonic-gate 	/* sanity clause */
6207c478bd9Sstevel@tonic-gate 	if (!g_kernelmode && (g_cmdname == NULL && g_targetpid == 0))
6217c478bd9Sstevel@tonic-gate 		usage(argv, gettext("need to specify cmd or pid"));
6227c478bd9Sstevel@tonic-gate 	if (g_cmdname != NULL && g_targetpid != 0)
6237c478bd9Sstevel@tonic-gate 		usage(argv, gettext("can't specify both cmd and pid"));
6247c478bd9Sstevel@tonic-gate 	if (g_targetpid && g_preload)
6257c478bd9Sstevel@tonic-gate 		usage(argv, gettext("can't use preload option with attach"));
6267c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
6277c478bd9Sstevel@tonic-gate 		if (g_outname)
6287c478bd9Sstevel@tonic-gate 			usage(argv, "can't specify a filename in kernel mode");
6297c478bd9Sstevel@tonic-gate 		if (g_cmdname)
6307c478bd9Sstevel@tonic-gate 			usage(argv, "can't specify a command in kernel mode");
6317c478bd9Sstevel@tonic-gate 		if (g_targetpid)
6327c478bd9Sstevel@tonic-gate 			usage(argv, "can't specify pid in kernel mode");
6337c478bd9Sstevel@tonic-gate 		if (g_preload)
6347c478bd9Sstevel@tonic-gate 			usage(argv, "can't use preload option in kernel mode");
6357c478bd9Sstevel@tonic-gate 	}
6367c478bd9Sstevel@tonic-gate 	/* default output size */
6377c478bd9Sstevel@tonic-gate 	if (g_outsize == -1)
6387c478bd9Sstevel@tonic-gate 		g_outsize = g_kernelmode ? KERNEL_OUTSIZE : USER_OUTSIZE;
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate #ifdef OLD
6417c478bd9Sstevel@tonic-gate 	int			 i;
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	for (i = 1; i < argc; i++) {
6447c478bd9Sstevel@tonic-gate 		if (strneq(argv[i], "-v", 2)) {
6457c478bd9Sstevel@tonic-gate 			int			 vlevel;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 			vlevel = (strlen(argv[i]) > 2)? atoi(&argv[i][2]) : 1;
6487c478bd9Sstevel@tonic-gate 			g_verbose = B_TRUE;
6497c478bd9Sstevel@tonic-gate 			prb_verbose_set(vlevel);
6507c478bd9Sstevel@tonic-gate 		} else if (strneq(argv[i], "-pid", 2)) {
6517c478bd9Sstevel@tonic-gate 			if (++i >= argc)
6527c478bd9Sstevel@tonic-gate 				usage(argv, gettext("missing pid argument"));
6537c478bd9Sstevel@tonic-gate 			g_targetpid = atoi(argv[i]);
6547c478bd9Sstevel@tonic-gate 		} else if (strneq(argv[i], "-t", 2)) {
6557c478bd9Sstevel@tonic-gate 			g_testflag = B_TRUE;
6567c478bd9Sstevel@tonic-gate 			(void) setvbuf(stdout, NULL, _IOLBF, 0);
6577c478bd9Sstevel@tonic-gate 		} else if (argv[i][0] != '-') {
6587c478bd9Sstevel@tonic-gate 			g_cmdname = strdup(argv[i]);
6597c478bd9Sstevel@tonic-gate 			if (!g_cmdname) {
6607c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
6617c478bd9Sstevel@tonic-gate 					"%s: out of memory"), argv[0]);
6627c478bd9Sstevel@tonic-gate 			}
6637c478bd9Sstevel@tonic-gate 			if (g_verbose >= 2) {
6647c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
6657c478bd9Sstevel@tonic-gate 					"cmdname=%s\n", g_cmdname);
6667c478bd9Sstevel@tonic-gate 			}
6677c478bd9Sstevel@tonic-gate 			/*
6687c478bd9Sstevel@tonic-gate 			 * rest of arguments are the args to the executable -
6697c478bd9Sstevel@tonic-gate 			 * by convention argv[0] should be name of
6707c478bd9Sstevel@tonic-gate 			 * executable, so we don't increment i
6717c478bd9Sstevel@tonic-gate 			 */
6727c478bd9Sstevel@tonic-gate 			g_cmdargs = &argv[i];
6737c478bd9Sstevel@tonic-gate 			break;
6747c478bd9Sstevel@tonic-gate 		} else {
6757c478bd9Sstevel@tonic-gate 			usage(argv, gettext("unrecognized argument"));
6767c478bd9Sstevel@tonic-gate 		}
6777c478bd9Sstevel@tonic-gate 	}
6787c478bd9Sstevel@tonic-gate #endif
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate }				/* end scanargs */
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate /*
6847c478bd9Sstevel@tonic-gate  * sig_handler() - cleans up if a signal is received
6857c478bd9Sstevel@tonic-gate  */
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6887c478bd9Sstevel@tonic-gate static void
6897c478bd9Sstevel@tonic-gate sig_handler(int signo)
6907c478bd9Sstevel@tonic-gate {
6917c478bd9Sstevel@tonic-gate 	g_getcmds = B_TRUE;
6927c478bd9Sstevel@tonic-gate }				/* end sig_handler */
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate /*
6967c478bd9Sstevel@tonic-gate  * set_signal() -  sets up function to call for clean up
6977c478bd9Sstevel@tonic-gate  */
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate static int
7007c478bd9Sstevel@tonic-gate set_signal(void)
7017c478bd9Sstevel@tonic-gate {
7027c478bd9Sstevel@tonic-gate 	struct sigaction newact;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	newact.sa_handler = sig_handler;
7057c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&newact.sa_mask);
7067c478bd9Sstevel@tonic-gate 	newact.sa_flags = 0;
7077c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &newact, NULL) < 0) {
7087c478bd9Sstevel@tonic-gate 		return (errno);
7097c478bd9Sstevel@tonic-gate 	}
7107c478bd9Sstevel@tonic-gate 	return (0);
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate  * set_tracefile() - initializes tracefile, sets the tracefile name and size
7167c478bd9Sstevel@tonic-gate  */
7177c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
7187c478bd9Sstevel@tonic-gate set_tracefile(tnfctl_handle_t *hndl)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	err;
7217c478bd9Sstevel@tonic-gate 	tnfctl_trace_attrs_t	attrs;
7227c478bd9Sstevel@tonic-gate 	size_t			minoutsize;
7237c478bd9Sstevel@tonic-gate 	char			path[MAXPATHLEN];
7247c478bd9Sstevel@tonic-gate 	char			*outfile_name;
7257c478bd9Sstevel@tonic-gate 	char			*tmpdir;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	/* Init tracefile name used by list cmd */
7287c478bd9Sstevel@tonic-gate 	tracefile = NULL;
7297c478bd9Sstevel@tonic-gate 	err = tnfctl_trace_attrs_get(hndl, &attrs);
7307c478bd9Sstevel@tonic-gate 	if (err)
7317c478bd9Sstevel@tonic-gate 		return (err);
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	if (attrs.trace_buf_state == TNFCTL_BUF_BROKEN)
7347c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_BUFBROKEN);
7357c478bd9Sstevel@tonic-gate 	if (attrs.trace_buf_state == TNFCTL_BUF_OK) {
7367c478bd9Sstevel@tonic-gate 		/* trace file set already - can't change it */
7377c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_NONE);
7387c478bd9Sstevel@tonic-gate 	}
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	minoutsize = attrs.trace_min_size;
7417c478bd9Sstevel@tonic-gate 	if (g_outsize < minoutsize)	{
7427c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
7437c478bd9Sstevel@tonic-gate 			gettext("specified tracefile size smaller then "
7447c478bd9Sstevel@tonic-gate 				"minimum; setting to %d kbytes\n"),
7457c478bd9Sstevel@tonic-gate 				minoutsize / 1024);
7467c478bd9Sstevel@tonic-gate 		g_outsize = minoutsize;
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	/* where is $TMPDIR? */
7507c478bd9Sstevel@tonic-gate 	tmpdir = getenv("TMPDIR");
7517c478bd9Sstevel@tonic-gate 	if (!tmpdir || *tmpdir == '\0') {
7527c478bd9Sstevel@tonic-gate 		tmpdir = "/tmp";
7537c478bd9Sstevel@tonic-gate 	}
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	/* do we have an absolute, relative or no pathname specified? */
7567c478bd9Sstevel@tonic-gate 	if (g_outname == NULL) {
7577c478bd9Sstevel@tonic-gate 		/* default, no tracefile specified */
7587c478bd9Sstevel@tonic-gate 		if ((strlen(tmpdir) + 1 + 20) > (size_t)MAXPATHLEN) {
7597c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
7607c478bd9Sstevel@tonic-gate 				"%s: $TMPDIR too long\n"), g_argv[0]);
7617c478bd9Sstevel@tonic-gate 			exit(1);
7627c478bd9Sstevel@tonic-gate 		}
7637c478bd9Sstevel@tonic-gate 		(void) sprintf(path, "%s/trace-%ld", tmpdir, g_targetpid);
7647c478bd9Sstevel@tonic-gate 		outfile_name = path;
7657c478bd9Sstevel@tonic-gate 	} else {
7667c478bd9Sstevel@tonic-gate 		/* filename specified */
7677c478bd9Sstevel@tonic-gate 		outfile_name = g_outname;
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 	tracefile = strdup(outfile_name);
7707c478bd9Sstevel@tonic-gate 	if (tracefile == NULL) {
7717c478bd9Sstevel@tonic-gate 		if ((errno == ENOMEM) || (errno == EAGAIN)) {
7727c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_ALLOCFAIL);
7737c478bd9Sstevel@tonic-gate 		} else {
7747c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_INTERNAL);
7757c478bd9Sstevel@tonic-gate 		}
7767c478bd9Sstevel@tonic-gate 	}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
7797c478bd9Sstevel@tonic-gate 	if (g_verbose)
7807c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
7817c478bd9Sstevel@tonic-gate 			"setting tracefile name=\"%s\", size=%d\n",
7827c478bd9Sstevel@tonic-gate 			path, g_outsize);
7837c478bd9Sstevel@tonic-gate #endif
7847c478bd9Sstevel@tonic-gate 	err = tnfctl_buffer_alloc(hndl, outfile_name, g_outsize);
7857c478bd9Sstevel@tonic-gate 	return (err);
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate /*
7887c478bd9Sstevel@tonic-gate  * get_data_model() - get the process data model from psinfo
7897c478bd9Sstevel@tonic-gate  *		      structure.
7907c478bd9Sstevel@tonic-gate  */
7917c478bd9Sstevel@tonic-gate #define	PROCFORMAT	"/proc/%d"
7927c478bd9Sstevel@tonic-gate static int
7937c478bd9Sstevel@tonic-gate get_data_model(pid_t pid)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate 	char	path[MAXPATHLEN];
7967c478bd9Sstevel@tonic-gate 	int	fd, dmodel = -1;
7977c478bd9Sstevel@tonic-gate 	prpsinfo_t	psinfo;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	(void) sprintf(path, PROCFORMAT, (int)pid);
8007c478bd9Sstevel@tonic-gate 	fd = open(path, O_RDONLY);
8017c478bd9Sstevel@tonic-gate 	if (fd == -1)
8027c478bd9Sstevel@tonic-gate 	    return (dmodel);
8037c478bd9Sstevel@tonic-gate 	if ((dmodel = ioctl(fd, PIOCPSINFO, &psinfo)) == -1)
8047c478bd9Sstevel@tonic-gate 	    return (dmodel);
8057c478bd9Sstevel@tonic-gate 	return ((int)psinfo.pr_dmodel);
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate /*
8087c478bd9Sstevel@tonic-gate  * get_executable - return file descriptor for PATH-resolved
8097c478bd9Sstevel@tonic-gate  *		    target file.
8107c478bd9Sstevel@tonic-gate  *
8117c478bd9Sstevel@tonic-gate  */
8127c478bd9Sstevel@tonic-gate static int
8137c478bd9Sstevel@tonic-gate get_executable(char *name) {
8147c478bd9Sstevel@tonic-gate     int fd = -1;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate     if (name != NULL) {
8177c478bd9Sstevel@tonic-gate 	char path[PATH_MAX + 1];
8187c478bd9Sstevel@tonic-gate 	char line[MAX_INPUT + 1];
8197c478bd9Sstevel@tonic-gate 	char *p = line;
8207c478bd9Sstevel@tonic-gate 	char *fname = name;
8217c478bd9Sstevel@tonic-gate 	int N = sizeof (line);
8227c478bd9Sstevel@tonic-gate 	struct stat file_att;
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	while (*fname == ' ') fname++;
8257c478bd9Sstevel@tonic-gate 	if (fname[0] == '-' || strchr(fname, '/')) {
8267c478bd9Sstevel@tonic-gate 	    fd = open(fname, O_RDONLY);
8277c478bd9Sstevel@tonic-gate 	} else {
8287c478bd9Sstevel@tonic-gate 	    int len = strlen(fname);
8297c478bd9Sstevel@tonic-gate 	    char *dirlist = getenv("PATH");
8307c478bd9Sstevel@tonic-gate 	    char *dir = NULL;
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 	    if (dirlist != NULL) {
8337c478bd9Sstevel@tonic-gate 		dirlist = strdup(dirlist);
8347c478bd9Sstevel@tonic-gate 		dir = strtok(dirlist, ":");
8357c478bd9Sstevel@tonic-gate 	    }
8367c478bd9Sstevel@tonic-gate 	    while (fd < 0 && dir != NULL) {
8377c478bd9Sstevel@tonic-gate 		if ((strlen(dir) + len + 1) < sizeof (path)) {
8387c478bd9Sstevel@tonic-gate 		    strcat(strcat(strcpy(path, dir), "/"), fname);
8397c478bd9Sstevel@tonic-gate 		    fd = open(path, O_RDONLY);
8407c478bd9Sstevel@tonic-gate 		}
8417c478bd9Sstevel@tonic-gate 		dir = strtok(NULL, ":");
8427c478bd9Sstevel@tonic-gate 	    }
8437c478bd9Sstevel@tonic-gate 	    if (dirlist != NULL) free(dirlist);
8447c478bd9Sstevel@tonic-gate 	}
8457c478bd9Sstevel@tonic-gate 	if (fstat(fd, &file_att) || !S_ISREG(file_att.st_mode)) {
8467c478bd9Sstevel@tonic-gate 	    if (fd >= 0)
8477c478bd9Sstevel@tonic-gate 		close(fd);
8487c478bd9Sstevel@tonic-gate 	    return (-1);
8497c478bd9Sstevel@tonic-gate 	}
8507c478bd9Sstevel@tonic-gate 	if (read(fd, p, 2) && p[0] == '#' && p[1] == '!') {
8517c478bd9Sstevel@tonic-gate 	    while (N-- > 1 && read(fd, p, 1) && *p != '\n')
8527c478bd9Sstevel@tonic-gate 		p++;
8537c478bd9Sstevel@tonic-gate 	    *p = '\0';
8547c478bd9Sstevel@tonic-gate 	    close(fd);
8557c478bd9Sstevel@tonic-gate 	    return (get_executable(line));
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 	if (fd >= 0) lseek(fd, 0, SEEK_SET);
8587c478bd9Sstevel@tonic-gate 	} /* %$#@! cstyle complaint */
8597c478bd9Sstevel@tonic-gate     return (fd);
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate /*
8637c478bd9Sstevel@tonic-gate  * get_elf_class - get the target executable elf class
8647c478bd9Sstevel@tonic-gate  *                 i.e. ELFCLASS64 or ELFCLASS32.
8657c478bd9Sstevel@tonic-gate  */
8667c478bd9Sstevel@tonic-gate static int
8677c478bd9Sstevel@tonic-gate get_elf_class(char *filename)
8687c478bd9Sstevel@tonic-gate {
8697c478bd9Sstevel@tonic-gate 	int	elfclass = -1;
8707c478bd9Sstevel@tonic-gate 	int	elffd = get_executable(filename);
8717c478bd9Sstevel@tonic-gate 	Elf	*elf;
8727c478bd9Sstevel@tonic-gate 	size_t	size;
8737c478bd9Sstevel@tonic-gate 	char	*ident;
8747c478bd9Sstevel@tonic-gate 	GElf_Ehdr	ehdr;
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	if (elffd < 0)
8777c478bd9Sstevel@tonic-gate 		return (elfclass);
8787c478bd9Sstevel@tonic-gate 	if (elf_version(EV_CURRENT) == EV_NONE) {
8797c478bd9Sstevel@tonic-gate 		(void) close(elffd);
8807c478bd9Sstevel@tonic-gate 		return (elfclass);
8817c478bd9Sstevel@tonic-gate 	}
8827c478bd9Sstevel@tonic-gate 	elf = elf_begin(elffd, ELF_C_READ, (Elf *) 0);
8837c478bd9Sstevel@tonic-gate 	/*
8847c478bd9Sstevel@tonic-gate 	 * verify information in file header
8857c478bd9Sstevel@tonic-gate 	 */
8867c478bd9Sstevel@tonic-gate 	if (gelf_getehdr(elf, &ehdr) == (GElf_Ehdr *) 0) {
8877c478bd9Sstevel@tonic-gate 		close(elffd);
8887c478bd9Sstevel@tonic-gate 		return (elfclass);
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 	ident = elf_getident(elf, &size);
8917c478bd9Sstevel@tonic-gate 	if (ident[EI_CLASS] == ELFCLASS32)
8927c478bd9Sstevel@tonic-gate 		elfclass = ELFCLASS32;
8937c478bd9Sstevel@tonic-gate 	if (ident[EI_CLASS] == ELFCLASS64)
8947c478bd9Sstevel@tonic-gate 		elfclass = ELFCLASS64;
8957c478bd9Sstevel@tonic-gate 	close(elffd);
8967c478bd9Sstevel@tonic-gate 	return (elfclass);
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate  * check_exec_model() - check the consistency between prex data model
9007c478bd9Sstevel@tonic-gate  *                      and target elf class and act accordingly
9017c478bd9Sstevel@tonic-gate  */
9027c478bd9Sstevel@tonic-gate static void
9037c478bd9Sstevel@tonic-gate check_exec_model(char **argv, char **envp)
9047c478bd9Sstevel@tonic-gate {
9057c478bd9Sstevel@tonic-gate 	int	elfclass;
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	elfclass = get_elf_class(g_cmdname);
9087c478bd9Sstevel@tonic-gate 	if (((elfclass == ELFCLASS32) && (prex_dmodel == PR_MODEL_ILP32)) ||
9097c478bd9Sstevel@tonic-gate 	    ((elfclass == ELFCLASS64) && (prex_dmodel == PR_MODEL_LP64)))
9107c478bd9Sstevel@tonic-gate 	    return;
9117c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_ILP32) &&
9127c478bd9Sstevel@tonic-gate 	    (elfclass == ELFCLASS64)) {
9137c478bd9Sstevel@tonic-gate 	    (void) fprintf(stderr, gettext(
9147c478bd9Sstevel@tonic-gate 		"Error: 32 bit prex can not exec 64 bit target\n"));
9157c478bd9Sstevel@tonic-gate 	    exit(1);
9167c478bd9Sstevel@tonic-gate 	}
9177c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_LP64) &&
9187c478bd9Sstevel@tonic-gate 	    (elfclass == ELFCLASS32))
9197c478bd9Sstevel@tonic-gate 	    prex_isaexec(argv, envp);
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate /*
9237c478bd9Sstevel@tonic-gate  * check_pid_model() - check the consistency between prex data model
9247c478bd9Sstevel@tonic-gate  *                     and target data model and act accordingly
9257c478bd9Sstevel@tonic-gate  */
9267c478bd9Sstevel@tonic-gate static void
9277c478bd9Sstevel@tonic-gate check_pid_model(char **argv, char **envp)
9287c478bd9Sstevel@tonic-gate {
9297c478bd9Sstevel@tonic-gate 	int	dmodel;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	dmodel = get_data_model(g_targetpid);
9327c478bd9Sstevel@tonic-gate 	if (prex_dmodel == dmodel)
9337c478bd9Sstevel@tonic-gate 		return;
9347c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_ILP32) &&
9357c478bd9Sstevel@tonic-gate 		(dmodel == PR_MODEL_LP64)) {
9367c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
9377c478bd9Sstevel@tonic-gate 		    "Error: 32 bit prex can not exec 64 bit target\n"));
9387c478bd9Sstevel@tonic-gate 		exit(1);
9397c478bd9Sstevel@tonic-gate 	}
9407c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_LP64) &&
9417c478bd9Sstevel@tonic-gate 		(dmodel == PR_MODEL_ILP32))
9427c478bd9Sstevel@tonic-gate 		prex_isaexec(argv, envp);
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate  * prex_isaexec() - there is only one case this function get called
9467c478bd9Sstevel@tonic-gate  *                  64 bit prex, 32 bit target, need to exec 32 bit
9477c478bd9Sstevel@tonic-gate  *                  prex here.
9487c478bd9Sstevel@tonic-gate  */
9497c478bd9Sstevel@tonic-gate static void
9507c478bd9Sstevel@tonic-gate prex_isaexec(char **argv, char **envp)
9517c478bd9Sstevel@tonic-gate {
9527c478bd9Sstevel@tonic-gate 	char path[PATH_MAX + sizeof (PREX32DIR)];
9537c478bd9Sstevel@tonic-gate 	strcat(strcat(strcpy(path, dirname(dirname(argv[0]))), PREX32DIR),
9547c478bd9Sstevel@tonic-gate 	    basename(argv[0]));
9557c478bd9Sstevel@tonic-gate 	if (get_elf_class(path) != ELFCLASS32)
9567c478bd9Sstevel@tonic-gate 	    strcpy(path, PREX32EXEC);
9577c478bd9Sstevel@tonic-gate 	argv[0] = path;
9587c478bd9Sstevel@tonic-gate 	(void) execve(path, argv, envp);
9597c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
9607c478bd9Sstevel@tonic-gate 	    gettext("%s: execve(\"%s\") failed\n"),
9617c478bd9Sstevel@tonic-gate 	    argv[0], path);
962*c5024742Srab 	exit(1);
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate void
9657c478bd9Sstevel@tonic-gate cmd_listtracefile()
9667c478bd9Sstevel@tonic-gate {
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
9697c478bd9Sstevel@tonic-gate 	    (void) fprintf(stderr,
9707c478bd9Sstevel@tonic-gate 		    gettext("There is no trace file in kernel mode!\n"));
9717c478bd9Sstevel@tonic-gate 	} else {
9727c478bd9Sstevel@tonic-gate 	    (void) printf(gettext("Current trace file is: %s\n"), tracefile);
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate }
975