Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
28
cde/lib/tt/bin/tttrace/Imakefile
Normal file
28
cde/lib/tt/bin/tttrace/Imakefile
Normal file
@@ -0,0 +1,28 @@
|
||||
XCOMM $XConsortium: Imakefile /main/14 1996/10/09 14:02:22 drk $
|
||||
|
||||
#define CplusplusSource YES
|
||||
DEPEND_DEFINES = $(CXXDEPENDINCLUDES)
|
||||
EXTRA_LOAD_FLAGS = ExtraLoadFlags $(UNSHARED_CXXLIB)
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
#include "../../tooltalk.tmpl"
|
||||
|
||||
DEFINES =
|
||||
INCLUDES = -I. -I../../lib
|
||||
|
||||
DEPLIBS = TtClientDepLibs
|
||||
LOCAL_LIBRARIES = TtClientLibs
|
||||
SYS_LIBRARIES =
|
||||
|
||||
#ifdef TtClientExtraLibs
|
||||
EXTRA_LIBRARIES = TtClientExtraLibs
|
||||
#endif
|
||||
|
||||
SRCS = tttrace.C tttrace_objs.C
|
||||
|
||||
OBJS = tttrace.o tttrace_objs.o
|
||||
|
||||
NormalCplusplusObjectRule()
|
||||
|
||||
ComplexCplusplusProgramTarget(tttrace)
|
||||
11
cde/lib/tt/bin/tttrace/admindefines
Normal file
11
cde/lib/tt/bin/tttrace/admindefines
Normal file
@@ -0,0 +1,11 @@
|
||||
XCOMM $XConsortium: admindefines /main/2 1996/05/07 19:19:11 drk $
|
||||
|
||||
#ifdef sun
|
||||
/*
|
||||
* Some tooltalk header files contain inline references to internal
|
||||
* functions. Attempting to compile with -g fails because these
|
||||
* inline references expand into unresolved symbols. Until tooltalk
|
||||
* is fixed force use of -g0. See CDExc20311 for details.
|
||||
*/
|
||||
# define DebuggableCplusplusDebugFlags -g0
|
||||
#endif
|
||||
464
cde/lib/tt/bin/tttrace/tttrace.C
Normal file
464
cde/lib/tt/bin/tttrace/tttrace.C
Normal file
@@ -0,0 +1,464 @@
|
||||
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
|
||||
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
|
||||
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
||||
//%% (c) Copyright 1993, 1994 Novell, Inc.
|
||||
//%% $TOG: tttrace.C /main/9 1999/10/14 18:38:47 mgreess $
|
||||
/*
|
||||
* @(#)tttrace.C 1.29 95/05/02
|
||||
*
|
||||
* Copyright (c) 1993 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#if defined(linux)
|
||||
# include <sys/poll.h>
|
||||
#else
|
||||
# include <poll.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "api/c/tt_c.h"
|
||||
#include "util/tt_string.h"
|
||||
#include "util/tt_port.h"
|
||||
#include "util/tt_gettext.h"
|
||||
#include "tttrace_objs.h"
|
||||
#include "tt_options.h"
|
||||
|
||||
#define SESSION_TRACE_OP "Session_Trace"
|
||||
|
||||
static _Tt_string progname = "tttrace";
|
||||
pid_t forked_pid = (pid_t) -1;
|
||||
int makequit = 0;
|
||||
int poll_timeout = -1;
|
||||
int exit_status = 0;
|
||||
int ttfd = 0;
|
||||
|
||||
static void install_signal_handler();
|
||||
static void sig_handler(int);
|
||||
static pid_t do_fork(_Tt_trace_optobj&);
|
||||
static void send_session_trace(_Tt_trace_optobj&);
|
||||
static int tail_pipe(int, _Tt_string&, pid_t, int);
|
||||
static int open_pipe(_Tt_string&, int*);
|
||||
static void send_on_exit();
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void print_usage_and_exit();
|
||||
int status = 0;
|
||||
int pipe_fd = -1;
|
||||
_Tt_string temp_name; // name of FIFO file
|
||||
_Tt_trace_optobj myopts; // processes command-line options
|
||||
setlocale( LC_ALL, "" );
|
||||
|
||||
install_signal_handler();
|
||||
|
||||
//
|
||||
// parse command-line options
|
||||
//
|
||||
|
||||
switch(myopts.getopts(argc, argv)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
print_usage_and_exit();
|
||||
break;
|
||||
case 2:
|
||||
exit(2);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Open the pipe for reading, if requested
|
||||
|
||||
if (myopts.pipe_name().len()) {
|
||||
status = open_pipe(myopts.pipe_name(), &pipe_fd);
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
|
||||
// Do fork, or send session_trace requests
|
||||
|
||||
pid_t child_pid = 0;
|
||||
int sink;
|
||||
switch(myopts.operation_mode()) {
|
||||
case FORK_COMMAND:
|
||||
(void) putenv(myopts.envstr());
|
||||
child_pid = do_fork(myopts);
|
||||
sink = STDERR_FILENO;
|
||||
break;
|
||||
case SESSION_TRACE:
|
||||
send_session_trace(myopts);
|
||||
sink = STDOUT_FILENO;
|
||||
break;
|
||||
default:
|
||||
exit(2);
|
||||
break;
|
||||
}
|
||||
|
||||
_Tt_string outfile;
|
||||
if (myopts.outfile( outfile ) && (outfile == "-")) {
|
||||
sink = STDOUT_FILENO;
|
||||
}
|
||||
|
||||
status = tail_pipe(pipe_fd, myopts.pipe_name(), child_pid, sink);
|
||||
|
||||
if (pipe_fd > 0) {
|
||||
|
||||
if (unlink( myopts.pipe_name()) != 0) {
|
||||
_Tt_string msg = progname.cat( ": " );
|
||||
msg = msg.cat( myopts.pipe_name() );
|
||||
perror( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit( status );
|
||||
}
|
||||
|
||||
//
|
||||
// Install sig_handler as the handler for all the signals it handles.
|
||||
//
|
||||
static void
|
||||
install_signal_handler()
|
||||
{
|
||||
_Tt_string err;
|
||||
err = err.cat( ": _tt_sigset(SIG" );
|
||||
if (_tt_sigset(SIGHUP, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("HUP)") );
|
||||
}
|
||||
if (_tt_sigset(SIGTERM, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("TERM)") );
|
||||
}
|
||||
if (_tt_sigset(SIGINT, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("INT)") );
|
||||
}
|
||||
if (_tt_sigset(SIGUSR1, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("USR1)") );
|
||||
}
|
||||
if (_tt_sigset(SIGUSR2, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("USR2)") );
|
||||
}
|
||||
if (_tt_sigset(SIGCHLD, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("CHLD)") );
|
||||
}
|
||||
if (_tt_sigset(SIGPIPE, &sig_handler) == 0) {
|
||||
perror( (char *) err.cat("PIPE)") );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Prints out a usage string and exits.
|
||||
//
|
||||
void
|
||||
print_usage_and_exit()
|
||||
{
|
||||
fprintf(stderr,
|
||||
catgets(_ttcatd, 9, 2,
|
||||
"Usage: %s [-0FCa][-o outfile] [-S session | command [options]]\n"
|
||||
" %s [-e script | -f scriptfile][-S session | command [options]]\n"
|
||||
" -0 Turn off message tracing in session, or run command\n"
|
||||
" without message tracing (i.e. only API tracing)\n"
|
||||
" -F Follow all children forked by command or subsequently\n"
|
||||
" started in session by ttsession(1)\n"
|
||||
" -C Do not trace ToolTalk API calls\n"
|
||||
" -a Print all attributes, arguments, and context slots of\n"
|
||||
" traced messages. Default is single-line summary.\n"
|
||||
" -e script Read tttracefile(4) settings from script\n"
|
||||
" -f scriptfile Read tttracefile(4) settings from scriptfile. \"-\": stdin.\n"
|
||||
" -o outfile Output. \"-\": stdout. default: stdout for session tracing,\n"
|
||||
" stderr (of tttrace) for command tracing\n"
|
||||
" -S session Session to trace. default: see tt_default_session()\n"
|
||||
" command ToolTalk client command to invoke and trace\n"),
|
||||
(char *) progname, (char *) progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Global signal handler for tttrace. All signals are handled by this
|
||||
// function (ie. no signal handlers should be defined in any other files)
|
||||
//
|
||||
static void
|
||||
sig_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
pid_t child;
|
||||
switch (sig) {
|
||||
case SIGPIPE:
|
||||
case SIGHUP:
|
||||
break;
|
||||
case SIGCHLD:
|
||||
child = waitpid( -1, &status, WNOHANG );
|
||||
if ((child > 0) && (WIFEXITED(status))) {
|
||||
exit_status = WEXITSTATUS(status);
|
||||
poll_timeout = 2;
|
||||
makequit = 1;
|
||||
}
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
makequit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static pid_t do_fork(_Tt_trace_optobj& myopts)
|
||||
{
|
||||
int i;
|
||||
int _tt_getdtablesize(void);
|
||||
int _tt_restoredtablesize(void);
|
||||
int maxfds; // max TT fd's
|
||||
_Tt_string cmd;
|
||||
|
||||
switch(forked_pid = fork()) {
|
||||
case -1:
|
||||
fprintf(stderr,"%s: fork(): %s\n", (char *)progname,
|
||||
strerror(errno));
|
||||
exit(2);
|
||||
case 0: // child
|
||||
maxfds = _tt_getdtablesize();
|
||||
for (i = 3; i < maxfds; i++) {
|
||||
close(i);
|
||||
}
|
||||
_tt_restoredtablesize();
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
(void) myopts.command(cmd); // existence of cmd already checked
|
||||
execvp((char *) cmd, (char * const*)myopts.cargv());
|
||||
perror((char *) progname);
|
||||
exit(1);
|
||||
default: // parent -- wait on child process
|
||||
break;
|
||||
}
|
||||
return forked_pid;
|
||||
}
|
||||
|
||||
static void send_session_trace(_Tt_trace_optobj& myopts)
|
||||
{
|
||||
int timeout = 180; // 3-minute timeout
|
||||
int script_stat;
|
||||
size_t num_fd = 1;
|
||||
struct pollfd fds[1];
|
||||
_Tt_string tmp;
|
||||
Tt_callback_action tttrace_callback(Tt_message, Tt_pattern);
|
||||
|
||||
Tt_message msg;
|
||||
|
||||
int mark = tt_mark();
|
||||
|
||||
// We must send the message to the specified session. This routine
|
||||
// is only called when there is an explicit session in the
|
||||
// options list.
|
||||
|
||||
myopts.session(tmp);
|
||||
|
||||
ttfd = tt_fd();
|
||||
|
||||
tt_session_join((char *) tmp);
|
||||
msg = tt_prequest_create(TT_SESSION, SESSION_TRACE_OP);
|
||||
|
||||
tt_message_arg_add(msg, TT_IN, "string", (char *) 0);
|
||||
script_stat = myopts.script(tmp);
|
||||
if (script_stat == 1) { // inline script
|
||||
tt_message_arg_val_set(msg, 0, (char *) tmp);
|
||||
}
|
||||
else if (script_stat == 2) { // script is in filename
|
||||
tt_message_file_set(msg, (char *) tmp);
|
||||
}
|
||||
|
||||
tt_message_callback_add(msg, tttrace_callback);
|
||||
Tt_status mstat = tt_message_send(msg);
|
||||
|
||||
if (mstat != TT_OK) {
|
||||
fprintf(stderr, "%s: tt_message_send(): %s\n",
|
||||
(char *) progname, tt_status_message(mstat));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
fds[0].fd = ttfd;
|
||||
fds[0].events = POLLIN | POLLPRI;
|
||||
fds[0].revents = 0;
|
||||
int rcode = poll(fds, num_fd, timeout);
|
||||
if (rcode == -1) {
|
||||
fprintf(stderr, "%s: Session_Trace: %s\n",
|
||||
(char *) progname, strerror(ETIMEDOUT));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
Tt_message inmsg = tt_message_receive();
|
||||
|
||||
// Make sure the stop-tracing message is sent upon exit
|
||||
|
||||
send_on_exit();
|
||||
|
||||
tt_release(mark);
|
||||
}
|
||||
|
||||
Tt_callback_action tttrace_callback(Tt_message msg, Tt_pattern)
|
||||
{
|
||||
Tt_status mstat = (Tt_status) tt_message_status(msg);
|
||||
if (mstat == TT_ERR_NO_MATCH) {
|
||||
|
||||
// ttsession does not recognize this message, which
|
||||
// means an incompatible version of ttsession is being
|
||||
// used
|
||||
|
||||
fprintf(stderr, catgets(_ttcatd, 9, 3,
|
||||
"%s: session <%s> does not support "
|
||||
"Session_Trace. Use kill -USR1 instead. "
|
||||
"See ttsession(1).\n"),
|
||||
(char *) progname, tt_message_session(msg) );
|
||||
exit(5);
|
||||
}
|
||||
else if (mstat != TT_OK) {
|
||||
fprintf(stderr, "%s: Session_Trace: %s\n",
|
||||
(char *) progname, tt_status_message(mstat));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return TT_CALLBACK_PROCESSED;
|
||||
}
|
||||
|
||||
static void send_on_exit()
|
||||
{
|
||||
Tt_message msg = tt_prequest_create(TT_SESSION, SESSION_TRACE_OP);
|
||||
tt_message_arg_add(msg, TT_IN, "string",
|
||||
"version 1; states none; functions none" );
|
||||
tt_message_send_on_exit(msg);
|
||||
}
|
||||
|
||||
#define MAXLINE 255
|
||||
|
||||
static int open_pipe(_Tt_string& pipe_name, int* fd)
|
||||
{
|
||||
int quit = 0;
|
||||
int exit_status = 0;
|
||||
|
||||
while ((! quit) && (*fd <= 0)) {
|
||||
*fd = open((char *) pipe_name, O_RDONLY | O_NDELAY);
|
||||
if ((*fd < 0) && (errno != EINTR)) {
|
||||
_Tt_string msg = progname.cat( ": " ).cat(pipe_name);
|
||||
perror(msg);
|
||||
exit_status = 2;
|
||||
}
|
||||
quit = 1;
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
|
||||
// No silly cracks about this routine's name, please!
|
||||
|
||||
static int tail_pipe(int fd, _Tt_string& pipenm, pid_t child_pid, int sink)
|
||||
{
|
||||
int bufsize = MAXLINE;
|
||||
int nbytes;
|
||||
int quit = 0;
|
||||
struct pollfd fds[2];
|
||||
char buf[MAXLINE];
|
||||
|
||||
if (pipenm.len() == 0) {
|
||||
int done = 0;
|
||||
while (!done) {
|
||||
pid_t child_waited_for = waitpid( child_pid, 0, 0 );
|
||||
if (child_waited_for < 0 && errno == EINTR) continue;
|
||||
if (child_waited_for < 0 && errno == ECHILD) break;
|
||||
if (child_waited_for < 0) {
|
||||
fprintf(stderr, "%s: waitpid(): ",
|
||||
(char *) progname);
|
||||
perror(0);
|
||||
if(errno == ECHILD){
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
done = 1;
|
||||
}
|
||||
} else {
|
||||
|
||||
while (!quit) {
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
fds[0].revents = 0;
|
||||
fds[1].fd = ttfd;
|
||||
fds[1].events = POLLIN;
|
||||
fds[1].revents = 0;
|
||||
|
||||
int numfds = poll(fds, ttfd ? 2 : 1, poll_timeout);
|
||||
if (numfds < 0) {
|
||||
if (errno != EINTR) {
|
||||
_Tt_string msg =
|
||||
progname.cat( ": poll()" );
|
||||
perror( msg );
|
||||
exit_status = 2;
|
||||
quit = 1;
|
||||
}
|
||||
else if (makequit) {
|
||||
quit = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (numfds == 0) {
|
||||
quit = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fds[ 0 ].revents & POLLHUP) {
|
||||
if (makequit) {
|
||||
|
||||
// Child has exited -- do a last read
|
||||
while ((nbytes = read(fd,
|
||||
buf,
|
||||
bufsize)) > 0) {
|
||||
write(sink, buf, nbytes);
|
||||
}
|
||||
quit = 1;
|
||||
}
|
||||
else {
|
||||
pid_t child_waited_for = waitpid(child_pid,
|
||||
0, 0 );
|
||||
if (child_waited_for == child_pid) {
|
||||
|
||||
quit = 1;
|
||||
}
|
||||
else {
|
||||
|
||||
// Tracing is temporarily stopped.
|
||||
// Periodically wake up to see if it
|
||||
// has started again.
|
||||
|
||||
sleep( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fds[ 0 ].revents & POLLIN) {
|
||||
if (makequit) {
|
||||
quit = 1;
|
||||
}
|
||||
else {
|
||||
nbytes = read(fd, buf, bufsize);
|
||||
if (nbytes > 0) {
|
||||
write(sink, buf, nbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fds[ 1 ].revents & POLLIN) {
|
||||
Tt_message msg = tt_message_receive();
|
||||
if (tt_ptr_error(msg) == TT_ERR_NOMP) {
|
||||
quit = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
return exit_status;
|
||||
}
|
||||
419
cde/lib/tt/bin/tttrace/tttrace_objs.C
Normal file
419
cde/lib/tt/bin/tttrace/tttrace_objs.C
Normal file
@@ -0,0 +1,419 @@
|
||||
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
|
||||
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
|
||||
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
||||
//%% (c) Copyright 1993, 1994 Novell, Inc.
|
||||
//%% $XConsortium: tttrace_objs.C /main/3 1995/10/20 17:02:43 rswiston $
|
||||
/*
|
||||
* @(#)tttrace_objs.C 1.4 93/11/04
|
||||
*
|
||||
* Copyright (c) 1993 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "tttrace_objs.h"
|
||||
#include "util/tt_trace.h"
|
||||
|
||||
_Tt_trace_optobj::_Tt_trace_optobj()
|
||||
{
|
||||
_msg_tracing = 1; // trace messages and calls by default
|
||||
_follow = 0; // follow off by default
|
||||
_api_calls = 1; // trace calls into API by default
|
||||
_all_attrs = 0; // short form by default
|
||||
_has_script_inline = 0;
|
||||
_has_script_filename = 0;
|
||||
_inline_or_filename = "version 1 ";
|
||||
_has_outfile = 0;
|
||||
_has_session = 2; // 1 -> -S option, 2 -> set by default
|
||||
_has_command = 0;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::getopts(int argc, char** argv)
|
||||
{
|
||||
int c; // command-line option char
|
||||
int i;
|
||||
|
||||
extern char* optarg; // command-line option
|
||||
extern int optind; // option index into argv
|
||||
extern int opterr; // getopt error value
|
||||
|
||||
_Tt_string tmpstr;
|
||||
_Tt_string tmppath;
|
||||
_Tt_string _tt_realpath(const _Tt_string&);
|
||||
|
||||
_form = NO_FORM;
|
||||
|
||||
// needed by the getopt call
|
||||
opterr = 0;
|
||||
while ((c = getopt(argc, argv, argstr)) != -1) {
|
||||
switch (c) {
|
||||
case '0':
|
||||
// Turn off msg tracing in <session> or run <command>
|
||||
// without message tracing
|
||||
if (_form == SCRIPT_FORM) return 1;
|
||||
_form = NOSCRIPT_FORM;
|
||||
_msg_tracing = 0;
|
||||
break;
|
||||
case 'F':
|
||||
// Follow children
|
||||
if (_form == SCRIPT_FORM) return 1;
|
||||
_form = NOSCRIPT_FORM;
|
||||
_follow = 1;
|
||||
break;
|
||||
case 'C':
|
||||
// Do not trace client calls into the TT API
|
||||
if (_form == SCRIPT_FORM) return 1;
|
||||
_form = NOSCRIPT_FORM;
|
||||
_api_calls = 0;
|
||||
break;
|
||||
case 'a':
|
||||
// verbose form
|
||||
if (_form == SCRIPT_FORM) return 1;
|
||||
_form = NOSCRIPT_FORM;
|
||||
_all_attrs = 1;
|
||||
break;
|
||||
case 'e':
|
||||
// command-line script
|
||||
if (_form == NOSCRIPT_FORM) return 1;
|
||||
_form = SCRIPT_FORM;
|
||||
|
||||
if (!_has_script_filename) {
|
||||
_inline_or_filename = optarg;
|
||||
_has_script_inline = 1;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
// script file
|
||||
if (_form == NOSCRIPT_FORM) return 1;
|
||||
_form = SCRIPT_FORM;
|
||||
|
||||
if (!_has_script_inline) {
|
||||
|
||||
struct stat sbuf;
|
||||
|
||||
tmppath = optarg;
|
||||
tmpstr = _tt_realpath(tmppath);
|
||||
_inline_or_filename = tmpstr;
|
||||
if (stat(_inline_or_filename, &sbuf) != 0) {
|
||||
fprintf(stderr, "ttrace: %s: %s\n",
|
||||
(char *)_inline_or_filename,
|
||||
strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
_has_script_filename = 1;
|
||||
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
// outfile
|
||||
if (_form == SCRIPT_FORM) return 1;
|
||||
_form = NOSCRIPT_FORM;
|
||||
_outfile = optarg;
|
||||
_has_outfile = 1;
|
||||
break;
|
||||
case 'S':
|
||||
// XXX: Note that a Session_Trace message *always*
|
||||
// gets sent when this option is given, so we have
|
||||
// to do a tt_open somewhere, and it may as well be
|
||||
// here, so we can do a tt_default_session if
|
||||
// necessary.
|
||||
|
||||
Tt_status tts;
|
||||
char* procid;
|
||||
|
||||
_session = optarg;
|
||||
tts = tt_default_session_set(_session);
|
||||
if (tts != TT_OK) {
|
||||
fprintf(stderr, "tttrace: "
|
||||
"tt_default_session_set:\n%s\n",
|
||||
tt_status_message(tts));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
procid = tt_open();
|
||||
tts = tt_ptr_error(procid);
|
||||
if (tts != TT_OK) {
|
||||
fprintf(stderr, "tttrace: tt_open:\n%s\n",
|
||||
tt_status_message(tts));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
_has_session = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
// error or help request.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
|
||||
// Command given after options
|
||||
|
||||
if (_has_session == 2) {
|
||||
|
||||
// Override the default
|
||||
_has_session = 0;
|
||||
}
|
||||
else if (_has_session == 1) {
|
||||
|
||||
// Can't give session and command together
|
||||
return 1;
|
||||
}
|
||||
|
||||
// command given after options
|
||||
|
||||
_command = argv[optind++];
|
||||
_cargv[0] = (char *) _command;
|
||||
for (i = 1; optind < argc; ++i, ++optind) {
|
||||
_cargv[i] = argv[optind];
|
||||
}
|
||||
_cargv[i] = (char *) 0;
|
||||
_has_command = 1;
|
||||
|
||||
} else if (_has_session == 2) {
|
||||
|
||||
// default -- tttrace with no session or command args
|
||||
|
||||
(void) tt_open();
|
||||
_session = tt_default_session();
|
||||
}
|
||||
|
||||
if ((! _has_outfile) || (_outfile == "-")) {
|
||||
|
||||
// We need to set up a FIFO to stuff the output
|
||||
// into, and give the FIFO name to the command/session
|
||||
|
||||
_pipenm = tempnam(NULL, "trace");
|
||||
if (mkfifo(_pipenm, S_IWUSR|S_IRUSR) == -1) {
|
||||
fprintf(stderr, "tttrace: mkfifo(\"%s\"): %s\n",
|
||||
(char *)_pipenm, strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
mkenvstr();
|
||||
|
||||
if (_form == NO_FORM) {
|
||||
_has_script_inline = 1;
|
||||
_form = SCRIPT_FORM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::msg_tracing()
|
||||
{
|
||||
return _msg_tracing;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::follow()
|
||||
{
|
||||
return _follow;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::api_calls()
|
||||
{
|
||||
return _api_calls;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::all_attrs()
|
||||
{
|
||||
return _all_attrs;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::script(_Tt_string& script_string)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!_msg_tracing) {
|
||||
|
||||
// _msg_tracing is 1 by default, so if it's zero here, it
|
||||
// means the -0 option was given, so whatever else was
|
||||
// specified by the command line is overridden by this
|
||||
|
||||
script_string = "states none";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (_has_script_inline) {
|
||||
ret = 1;
|
||||
}
|
||||
else if (_has_script_filename) {
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
script_string = _inline_or_filename;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::outfile(_Tt_string& filename)
|
||||
{
|
||||
filename = _outfile;
|
||||
|
||||
if (_has_outfile) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::session(_Tt_string& session_string)
|
||||
{
|
||||
session_string = _session;
|
||||
|
||||
if (_has_session) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::command(_Tt_string& command_string)
|
||||
{
|
||||
command_string = _command;
|
||||
|
||||
if (_has_command) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char**
|
||||
_Tt_trace_optobj::cargv()
|
||||
{
|
||||
return _cargv;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::mkenvstr()
|
||||
{
|
||||
char *val = getenv(TRACE_SCRIPT);
|
||||
if ((val != 0) && (_form == NO_FORM)) {
|
||||
_envstr = val;
|
||||
if (_inline_or_filename[0] == '/' ||
|
||||
_inline_or_filename[0] == '.') {
|
||||
|
||||
_form = NOSCRIPT_FORM; // filename
|
||||
}
|
||||
else {
|
||||
|
||||
_form = SCRIPT_FORM; // inline script
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_envstr = TRACE_SCRIPT;
|
||||
_envstr = _envstr.cat("=");
|
||||
|
||||
if (! _has_script_filename) {
|
||||
//
|
||||
// The script will be inline, instead of in a file
|
||||
//
|
||||
if ((! _has_outfile) || (_outfile == "-")) {
|
||||
//
|
||||
// No -o, so prepend "> pipe; " onto script
|
||||
//
|
||||
if (_pipenm.len() > 0) {
|
||||
_Tt_string output_cmd = "> ";
|
||||
output_cmd = output_cmd.cat(_pipenm).cat("; ");
|
||||
_inline_or_filename =
|
||||
output_cmd.cat( _inline_or_filename );
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// -o option overrides ">" in script, so
|
||||
// append "; > outfile" to script
|
||||
//
|
||||
if (_outfile.len() > 0) {
|
||||
_Tt_string output_cmd = "> ";
|
||||
output_cmd = output_cmd.cat(_outfile);
|
||||
if (_inline_or_filename.len() > 0) {
|
||||
_inline_or_filename =
|
||||
_inline_or_filename.cat("; ");
|
||||
}
|
||||
_inline_or_filename =
|
||||
_inline_or_filename.cat( output_cmd );
|
||||
}
|
||||
}
|
||||
//
|
||||
} else {
|
||||
// XXX if both -o and -f, we need to read the file!
|
||||
}
|
||||
if (!_has_script_inline && !_has_script_filename) {
|
||||
if (! _msg_tracing) {
|
||||
_inline_or_filename =
|
||||
_inline_or_filename.cat("; states none");
|
||||
}
|
||||
|
||||
if (_follow) {
|
||||
_inline_or_filename =
|
||||
_inline_or_filename.cat("; follow on");
|
||||
}
|
||||
|
||||
if (!_api_calls) {
|
||||
_inline_or_filename =
|
||||
_inline_or_filename.cat("; functions none");
|
||||
}
|
||||
|
||||
if (_all_attrs) {
|
||||
_inline_or_filename =
|
||||
_inline_or_filename.cat("; attributes all");
|
||||
}
|
||||
|
||||
_has_script_inline = 1;
|
||||
}
|
||||
|
||||
_envstr = _envstr.cat(_inline_or_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
_Tt_trace_optobj::operation_mode()
|
||||
{
|
||||
if (_has_session)
|
||||
return SESSION_TRACE;
|
||||
else if (_has_command) // _has_command
|
||||
return FORK_COMMAND;
|
||||
else
|
||||
return -1; // error
|
||||
}
|
||||
|
||||
_Tt_string
|
||||
_Tt_trace_optobj::envstr()
|
||||
{
|
||||
return _envstr;
|
||||
}
|
||||
|
||||
_Tt_string&
|
||||
|
||||
_Tt_trace_optobj::pipe_name()
|
||||
{
|
||||
return _pipenm;
|
||||
}
|
||||
|
||||
|
||||
120
cde/lib/tt/bin/tttrace/tttrace_objs.h
Normal file
120
cde/lib/tt/bin/tttrace/tttrace_objs.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
|
||||
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
|
||||
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
|
||||
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
|
||||
/*%% $XConsortium: tttrace_objs.h /main/3 1995/10/20 17:02:51 rswiston $ */
|
||||
/*
|
||||
* @(#)tttrace_objs.h 1.2 93/11/04
|
||||
*
|
||||
* Copyright (c) 1993 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "util/tt_string.h"
|
||||
|
||||
#define NO_FORM 0
|
||||
#define NOSCRIPT_FORM 1
|
||||
#define SCRIPT_FORM 2
|
||||
|
||||
#define FORK_COMMAND 0
|
||||
#define SESSION_TRACE 1
|
||||
|
||||
#define MAXARGS 256
|
||||
|
||||
#define argstr "0FCao:e:f:S:"
|
||||
|
||||
class _Tt_trace_optobj : public _Tt_object {
|
||||
|
||||
public:
|
||||
|
||||
// If msg_tracing is 0, only do client tracing. If 1, then
|
||||
// do message and client tracing
|
||||
|
||||
|
||||
int msg_tracing();
|
||||
|
||||
// If follow is 1, then trace all children forked
|
||||
|
||||
int follow();
|
||||
|
||||
// If api_calls is 1, trace client calls into the TT API
|
||||
|
||||
int api_calls();
|
||||
|
||||
// if all_attrs is 1, use long form
|
||||
|
||||
int all_attrs();
|
||||
|
||||
// if script returns 1, there is a script specified, and
|
||||
// the text of the script will be in script_string.
|
||||
// if script returns 2, the script is a filename
|
||||
|
||||
int script(_Tt_string& script_string);
|
||||
|
||||
// if outfile returns 1, there is an outfile specified, and
|
||||
// its value will be in filename
|
||||
|
||||
int outfile(_Tt_string& filename);
|
||||
|
||||
// if session returns 1, there is a session specified, and
|
||||
// its value will be in session_string
|
||||
|
||||
int session(_Tt_string& session_string);
|
||||
|
||||
// if command returns 1, there is a command specified, and
|
||||
// its value will be in command_string
|
||||
|
||||
int command(_Tt_string& command_string);
|
||||
|
||||
// argv for command
|
||||
|
||||
char** cargv();
|
||||
|
||||
// envstr returns a string suitable for putenv(), which is
|
||||
// used if a command is forked
|
||||
|
||||
_Tt_string envstr();
|
||||
|
||||
// Name of named pipe returned by tempnam
|
||||
|
||||
_Tt_string& pipe_name();
|
||||
|
||||
// constructor
|
||||
|
||||
_Tt_trace_optobj();
|
||||
|
||||
// do command-line processing
|
||||
|
||||
int getopts(int argc, char** argv);
|
||||
|
||||
// tttrace operates in two rundamental modes:
|
||||
// - fork command, using specified script or script file,
|
||||
// or command-line args as the script
|
||||
// - send session_trace requests, using specified script or script file
|
||||
|
||||
int operation_mode();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
int _form; // discriminates allowed options
|
||||
int _msg_tracing;
|
||||
int _follow;
|
||||
int _api_calls;
|
||||
int _all_attrs;
|
||||
int _has_script_inline;
|
||||
int _has_script_filename;
|
||||
_Tt_string _inline_or_filename;
|
||||
int _has_outfile;
|
||||
_Tt_string _outfile;
|
||||
int _has_session;
|
||||
_Tt_string _session;
|
||||
int _has_command;
|
||||
_Tt_string _command;
|
||||
char* _cargv[MAXARGS];
|
||||
_Tt_string _envstr;
|
||||
_Tt_string _pipenm;
|
||||
|
||||
|
||||
int mkenvstr(); // makes string for putenv();
|
||||
};
|
||||
Reference in New Issue
Block a user