cdesktopenv/cde/programs/ttsnoop/ttsnoop.C.src

802 lines
22 KiB
Plaintext

/*** DTB_USER_CODE_START vvv Add file header below vvv ***/
/* $TOG: ttsnoop.C.src /main/8 1999/09/20 16:07:27 mgreess $ */
/*** DTB_USER_CODE_END ^^^ Add file header above ^^^ ***/
/*
* File: ttsnoop.c
* Contains: main() and cross-module connections
*
* This file was generated by dtcodegen, from project ttsnoop
*
* Any text may be added between the DTB_USER_CODE_START and
* DTB_USER_CODE_END comments (even non-C code). Descriptive comments
* are provided only as an aid.
*
* ** EDIT ONLY WITHIN SECTIONS MARKED WITH DTB_USER_CODE COMMENTS. **
* ** ALL OTHER MODIFICATIONS WILL BE OVERWRITTEN. DO NOT MODIFY OR **
* ** DELETE THE GENERATED COMMENTS! **
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/MwmUtil.h>
#include <Xm/Protocols.h>
#include <Dt/Help.h>
#include <Dt/HelpQuickD.h>
#include <Dt/HelpDialog.h>
#include <unistd.h>
#include <Dt/Session.h>
#include <Dt/Term.h>
#include "ttsnoop_ui.h"
#include "apiTracer_ui.h"
#include "ttChooser_ui.h"
#include "patternProps_ui.h"
#include "stringChooser_ui.h"
#include "messageProps_ui.h"
#include "sessionChooser_ui.h"
#include "fileChooser_ui.h"
#include "argChooser_ui.h"
#include "callbackChooser_ui.h"
#include "ttsnoop.h"
#include "dtb_utils.h"
/**************************************************************************
*** DTB_USER_CODE_START
***
*** All necessary header files have been included.
***
*** Add include files, types, macros, externs, and user functions here.
***/
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <time.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <Dt/Term.h>
#include <Tt/tt_c.h>
#include <Tt/tttk.h>
#include "tt_c++.h"
#include "DtTt.h"
//#include <Xm/ColorObj.h>
//#include <Xm/ColorObjP.h>
//extern "C" { Pixmap XmeGetMask( Screen *, const char * ); }
Boolean optImmediateTracing = False;
Boolean optMapOnOutput = False;
Boolean optImmediateSnooping = True;
Boolean optImmediateTtOpen = True;
Boolean optImmediateXSession = False;
char * optImmediateSession = 0;
Tt_pattern snoopPat = 0;
Boolean snoopPatIsRegistered = False;
char * snoopFile = 0;
Boolean unlinkSnoopFile = True;
char * traceFile = 0;
Boolean unlinkTraceFile = True;
std::string traceScript;
int globalTimeout = 20000;
unsigned int globalSaveLines = 5000;
const char * globalVersionString = "1.0";
char ** scopeFiles = 0;
unsigned int scopeFilesCount = 0;
char ** ops = 0;
unsigned int opsCount = 0;
char ** senders = 0;
unsigned int sendersCount = 0;
char * vtype = 0;
pid_t snoopedPid = -1;
char ** snoopedArgs = 0;
unsigned int snoopedArgsCount = 0;
char * optTraceScript = 0;
String apiTracerArgv[ 10 ];
String snooperArgv[ 10 ];
std::ostringstream tttraceCmd;
std::ofstream snoopStream;
// Xt squats on -tf ?! XXX
const char Usage[] =
"ttsnoop - ToolTalk graphical user interface\n"
"Usage: ttsnoop [options] [-F scopefile] [-< procid] [-v media] [-m op]\n"
" ttsnoop [options] -n|-N\n"
" ttsnoop [options] [-e script] command [args]\n"
"\n"
"-F scopefile scope initial pattern also to scopefile\n"
"-\\< \"procid\" limit initial pattern to messages from procid\n"
"-v mediaType limit initial pattern to messages for mediaType\n"
"-m op limit initial pattern to given op\n"
"\n"
"-n skip initial pattern\n"
"-N skip initial ttdt_open(), also\n"
"\n"
"command [args] invoke command [with args] and snoop its TT API calls\n"
"-e script Take script as a tttrace setting. See tttracefile(4).\n"
"\n"
"options ::= [-Tu] [-S sessid] [-w n] [-l n] [-o snoopfile] [-O tracefile]\n"
"-T trace (even initial) TT API calls made by ttsnoop\n"
"-u map (de-iconify) on snoop output\n"
"-S sessid set default session to sessid\n"
"-X set default session to tt_X_session of $DISPLAY\n"
"-w n set global timeout to n seconds [default: 20]\n"
"-l n set tttrace dtterm saveLines to n lines [default: 5000]\n"
"-o snoopfile log snoop output to snoopfile\n"
"-O tracefile log api tracing to tracefile\n"
"\n"
"-xrm \"*DtTerm.saveLines: n\"\n"
"-xrm \"*DtTerm.rows: n\"\n"
"-xrm \"*DtTerm.columns: n\"\n"
"-xrm \"*DtTerm.mapOnOutput: true\"\n";
static void
cleanUp()
{
if (unlinkSnoopFile) {
if (unlink( snoopFile ) == -1) {
clog << "ttsnoop: unlink( \"" << snoopFile;
clog << "\"): " << strerror( errno ) << endl;
} else {
unlinkSnoopFile = False;
}
}
if (unlinkTraceFile) {
if (unlink( traceFile ) == -1) {
clog << "ttsnoop: unlink( \"" << traceFile;
clog << "\"): " << strerror( errno ) << endl;
} else {
unlinkTraceFile = False;
}
}
}
static void
signalHandler(
int sig
)
{
pid_t child;
int status;
switch (sig) {
case SIGHUP:
case SIGINT:
case SIGQUIT:
case SIGPIPE:
case SIGTERM:
exit( 5 );
case SIGCHLD:
child = waitpid( snoopedPid, &status, WNOHANG );
if ((child > 0) && WIFEXITED( status )) {
snoopStream << endl << endl << "SIGCHLD: WEXITSTATUS=="
<< WEXITSTATUS(status) << ": "
<< tttraceCmd.str().c_str() << endl << endl;
}
break;
case SIGCONT:
break;
}
}
#if defined(SVR4) || defined(aix) || defined(hpux) || defined(__linux__) || defined(CSRG_BASED)
#if !defined(SIG_PF)
typedef void (*sig_pf_t)(int);
#define SIG_PF sig_pf_t
#endif
#endif
int
_tt_sigset(
int sig,
SIG_PF handler )
{
#if defined(hpux) || defined(__linux__) || defined(CSRG_BASED)
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
return 0==sigaction(sig, &act, NULL);
#elif defined(OPT_BSD_SIGNAL)
return SIG_ERR!=signal(sig, handler);
#else
return SIG_ERR!=sigset(sig, handler);
#endif
}
static void
installSignalHandler()
{
_tt_sigset( SIGHUP, signalHandler );
_tt_sigset( SIGINT, signalHandler );
_tt_sigset( SIGQUIT, signalHandler );
_tt_sigset( SIGPIPE, signalHandler );
_tt_sigset( SIGTERM, signalHandler );
_tt_sigset( SIGCHLD, signalHandler );
_tt_sigset( SIGCONT, signalHandler );
atexit( cleanUp );
}
void
snoopIt(
const char *callBackType,
void *callBack,
Tt_message msg,
Tt_pattern pat,
Boolean printPat
)
{
if (snoopStream.bad()) {
return;
}
char timeBuf[ 16 ];
time_t now = time( 0 );
strftime( timeBuf, sizeof( timeBuf ), "%T", localtime( &now ));
snoopStream << timeBuf << " (" << callBackType << ")" << callBack;
snoopStream << "( " << "(Tt_message)" << (void *)msg << ", ";
if (printPat) {
snoopStream << "(Tt_pattern)" << (void *)pat;
} else {
snoopStream << "...";
}
snoopStream << " ): ";
char *msgString = tt_message_print( msg );
Tt_status status = tt_ptr_error( msgString );
if (status == TT_OK) {
snoopStream << endl << msgString << endl;
} else {
snoopStream << status << endl;
}
tt_free( msgString );
}
static Tt_callback_action
justSnoopIt(
Tt_message msg,
Tt_pattern pat
)
{
DtTtCreated( DTTT_MESSAGE, msg ); // XXX bad idea?
snoopIt( "Tt_callback_action", (void *) justSnoopIt, msg, pat, True );
return TT_CALLBACK_PROCESSED;
}
Tt_message
_DtTtMediaLoadPatCb(
Tt_message msg,
void *clientdata,
Tttk_op op,
Tt_status diagnosis,
unsigned char *contents,
int len,
char *file,
char *docname
)
{
tt_free( (caddr_t)contents );
tt_free( file );
tt_free( docname );
snoopIt( "Ttmedia_load_pat_cb", (void *) _DtTtMediaLoadPatCb, msg );
return 0;
}
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/
/*
* command line options...
*/
static XrmOptionDescRec optionDescList[] = {
{"-session", "*session", XrmoptionSepArg, (XPointer)NULL}
/*** DTB_USER_CODE_START vvv Add structure fields below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add structure fields above ^^^ ***/
};
/*
* Application Resources
*/
static XtResource resources[] = {
{"session", "Session", XtRString, sizeof(String),
XtOffsetOf(DtbAppResourceRec, session_file), XtRImmediate, (XtPointer)NULL}
/*** DTB_USER_CODE_START vvv Add structure fields below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add structure fields above ^^^ ***/
};
DtbAppResourceRec dtb_app_resource_rec;
/*
* main for application ttsnoop
*/
int
main(int argc, char **argv)
{
Widget toplevel = NULL;
Display *display = NULL;
XtAppContext app;
Atom save_yourself_atom;
Pixmap icon_pixmap = 0;
Pixmap icon_mask_pixmap = 0;
/**************************************************************************
*** DTB_USER_CODE_START
***
*** No initialization has been done.
***
*** Add local variables and code.
***/
/*
* The application must call DtTermInitialize() before
* initializing the Xt Toolkit with XtAppInitialize(3X).
*/
DtTermInitialize();
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/
toplevel = XtVaAppInitialize(&app, "Ttsnoop",
optionDescList, XtNumber(optionDescList),
&argc, argv, (String *)NULL,
(ArgList) NULL, 0);
/*
* Get display and verify initialization was successful.
*/
if (toplevel != NULL)
{
display = XtDisplayOfObject(toplevel);
}
if (display == NULL)
{
fprintf(stderr, "Could not open display.");
exit(1);
}
/*
* Save the toplevel widget so it can be fetched later as needed.
*/
dtb_save_toplevel_widget(toplevel);
/*
* Save the command used to invoke the application.
*/
dtb_save_command(argv[0]);
XtGetApplicationResources(toplevel, (XtPointer)&dtb_app_resource_rec,
resources, XtNumber(resources), (Arg *)NULL, 0);
/**************************************************************************
*** DTB_USER_CODE_START
***
*** A connection to the X server has been established, and all
*** initialization has been done.
***
*** Add extra initialization code after this comment.
***/
/*
PixelSet pixels[MAX_NUM_COLORS];
int colorUse;
short act, inact, prim, second;
XmeGetPixelData( DefaultScreen( display ), &colorUse, pixels,
&act, &inact, &prim, &second );
Pixmap pixmap = XmGetPixmap( DefaultScreenOfDisplay( display ),
"DtTtsnp.l", pixels[1].fg, pixels[1].bg );
XtVaSetValues( toplevel, XmNiconPixmap, pixmap, NULL) ;
pixmap = XmeGetMask( XtScreen( toplevel ), "DtTtsnp.l" );
XtVaSetValues( toplevel, XmNiconMask, pixmap, NULL) ;
*/
Boolean committed2Snooping = False;
int c;
while ((c = getopt(argc, argv, "?F:<:v:nNe:TuS:Xw:l:o:O:")) != -1) {
switch (c) {
case 'F':
if (! optImmediateSnooping) {
clog << Usage; exit( 2 );
}
committed2Snooping = 1;
listAppend( scopeFiles, scopeFilesCount, char *, optarg );
break;
case '<':
if (! optImmediateSnooping) {
clog << Usage; exit( 2 );
}
committed2Snooping = 1;
listAppend( senders, sendersCount, char *, optarg );
break;
case 'v':
if ((! optImmediateSnooping) || (vtype != 0)) {
clog << Usage; exit( 2 );
}
committed2Snooping = 1;
vtype = optarg;
break;
case 'm':
if (! optImmediateSnooping) {
clog << Usage; exit( 2 );
}
committed2Snooping = 1;
listAppend( ops, opsCount, char *, optarg );
break;
case 'n':
if (committed2Snooping) {
clog << Usage; exit( 2 );
}
optImmediateSnooping = False;
break;
case 'N':
if (committed2Snooping) {
clog << Usage; exit( 2 );
}
optImmediateSnooping = False;
optImmediateTtOpen = False;
break;
case 'e':
optTraceScript = optarg;
break;
case 'T':
optImmediateTracing = True;
break;
case 'u':
optMapOnOutput = True;
break;
case 'S':
if (optImmediateSession != 0) {
clog << Usage; exit( 2 );
}
optImmediateSession = optarg;
break;
case 'X':
if (optImmediateSession != 0) {
clog << Usage; exit( 2 );
}
optImmediateXSession = True;
break;
case 'w':
globalTimeout = atoi( optarg );
if (globalTimeout > 0) {
globalTimeout *= 1000;
}
break;
case 'l':
globalSaveLines = atoi( optarg );
break;
case 'o':
if (snoopFile != 0) {
clog << Usage; exit( 2 );
}
snoopFile = optarg;
unlinkSnoopFile = False;
break;
case 'O':
if (traceFile != 0) {
clog << Usage; exit( 2 );
}
traceFile = optarg;
unlinkTraceFile = False;
break;
case '?':
default:
clog << Usage; exit( 2 );
}
}
installSignalHandler();
if (traceFile == 0) {
//
// Set up fifo for trace output
//
traceFile = tempnam( 0, "ttsnt" );
if (mkfifo( traceFile, S_IWUSR | S_IRUSR ) == -1) {
clog << "ttsnoop: mkfifo( \"" << traceFile << "\" ) = ";
clog << strerror( errno ) << endl;
}
}
apiTracerArgv[ 0 ] = "tail";
apiTracerArgv[ 1 ] = "-n";
apiTracerArgv[ 2 ] = "+0";
apiTracerArgv[ 3 ] = "-f";
apiTracerArgv[ 4 ] = traceFile;
if (snoopFile == 0) {
//
// Set up fifo for snoop output
//
snoopFile = tempnam( 0, "ttsnp" );
if (mkfifo( snoopFile, S_IWUSR | S_IRUSR ) == -1) {
clog << "ttsnoop: mkfifo( \"" << snoopFile << "\" ) = ";
clog << strerror( errno ) << endl;
}
}
snooperArgv[ 0 ] = "tail";
snooperArgv[ 1 ] = "-n";
snooperArgv[ 2 ] = "+0";
snooperArgv[ 3 ] = "-f";
snooperArgv[ 4 ] = snoopFile;
if (optind < argc) {
if (committed2Snooping) {
clog << Usage; exit( 2 );
}
optImmediateSnooping = False;
optImmediateTtOpen = False;
listAppend( snoopedArgs, snoopedArgsCount, char *, "tttrace" );
listAppend( snoopedArgs, snoopedArgsCount, char *, "-o" );
listAppend( snoopedArgs, snoopedArgsCount, char *, snoopFile );
tttraceCmd << "tttrace -o " << snoopFile;
if (optTraceScript != 0) {
listAppend( snoopedArgs, snoopedArgsCount, char *, "-e" );
listAppend( snoopedArgs, snoopedArgsCount, char *,
optTraceScript );
tttraceCmd << " -e \"" << optTraceScript << "\"";
}
for (int i = optind; i < argc; i++) {
listAppend( snoopedArgs, snoopedArgsCount, char *,
argv[i] );
tttraceCmd << " " << argv[i];
}
tttraceCmd << ends;
listAppend( snoopedArgs, snoopedArgsCount, char *, 0 );
}
#if defined(aix)
#define AIX_STRING_LIST (char * const *)
#else
#define AIX_STRING_LIST
#endif
if (snoopedArgsCount > 0) {
snoopedPid = fork();
switch (snoopedPid) {
case -1:
clog << "ttsnoop: fork(): " << strerror( errno ) << endl;
exit( 3 );
case 0:
execvp( snoopedArgs[0], AIX_STRING_LIST snoopedArgs );
clog << "ttsnoop: execvp(): " << strerror( errno ) << endl;
exit( 3 );
}
installSignalHandler();
}
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/
/*
* Initialize all global variables.
*/
dtbTtsnoopTtsnoopWinInfo_clear(&dtb_ttsnoop_ttsnoop_win);
dtbApiTracerTracerInfo_clear(&dtb_api_tracer_tracer);
dtbTtChooserChooserInfo_clear(&dtb_tt_chooser_chooser);
dtbPatternPropsPatternPropsInfo_clear(&dtb_pattern_props_pattern_props);
dtbStringChooserStringChooserInfo_clear(&dtb_string_chooser_string_chooser);
dtbMessagePropsMessagePropsInfo_clear(&dtb_message_props_message_props);
dtbSessionChooserSessionChooserInfo_clear(&dtb_session_chooser_session_chooser);
dtbFileChooserFchooserInfo_clear(&dtb_file_chooser_fchooser);
dtbArgChooserArgChooserInfo_clear(&dtb_arg_chooser_arg_chooser);
dtbCallbackChooserCallbackChooserInfo_clear(&dtb_callback_chooser_callback_chooser);
/*
* Set up the application's root window.
*/
dtb_ttsnoop_ttsnoop_win.ttsnoopWin = toplevel;
dtb_cvt_image_file_to_pixmap(dtb_ttsnoop_ttsnoop_win.ttsnoopWin,
"DtTtsnp.l", &icon_pixmap);
dtb_cvt_image_file_to_pixmap(dtb_ttsnoop_ttsnoop_win.ttsnoopWin,
"DtTtsnp.l_m", &icon_mask_pixmap);
XtVaSetValues(dtb_ttsnoop_ttsnoop_win.ttsnoopWin,
XmNallowShellResize, True,
XmNtitle, "ttsnoop",
XmNiconMask, icon_mask_pixmap,
XmNiconPixmap, icon_pixmap,
XmNbackground, dtb_cvt_string_to_pixel(dtb_ttsnoop_ttsnoop_win.ttsnoopWin, "white"),
NULL);
dtb_ttsnoop_ttsnoop_win_initialize(&(dtb_ttsnoop_ttsnoop_win), dtb_get_toplevel_widget());
/*
* Map any initially-visible windows
*/
save_yourself_atom = XmInternAtom(XtDisplay(toplevel),
"WM_SAVE_YOURSELF", False);
dtb_set_client_session_saveCB((DtbClientSessionSaveCB)NULL);
XmAddWMProtocolCallback(toplevel, save_yourself_atom,
dtb_session_save, (XtPointer)NULL);
/**************************************************************************
*** DTB_USER_CODE_START
***
*** All initially-mapped widgets have been created, but not
*** realized. Set resources on widgets, or perform other operations
*** that must be completed before the toplevel widget is
*** realized.
***/
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/
XtRealizeWidget(toplevel);
/**************************************************************************
*** DTB_USER_CODE_START
***
*** The initially-mapped widgets have all been realized, and
*** the Xt main loop is about to be entered.
***/
installSignalHandler();
if (snoopedArgsCount > 0) {
DtTtSetLabel( dtb_ttsnoop_ttsnoop_win.ttsnoopWin_label,
tttraceCmd.str().c_str() );
}
Tt_status status;
snoopStream.open( snoopFile, ios::app );
std::ostringstream envStr;
envStr << "TT_TRACE_SCRIPT=> ";
envStr << traceFile << ends;
traceScript = envStr.str();
if (optImmediateTracing) {
turnOnTracing( 0, 0, 0 );
}
if (optImmediateXSession) {
char *display = getenv( "DISPLAY" );
optImmediateSession = tt_X_session( display );
status = tt_ptr_error( optImmediateSession );
if (tt_is_err( status )) {
clog << "ttsnoop: tt_X_session( ";
if (display == 0) {
clog << "0";
} else {
clog << "\"" << display << "\"";
}
clog << " ) = " << (void *)optImmediateSession;
clog << " (" << status << ")" << endl;
exit( 4 );
}
}
if (optImmediateSession != 0) {
status = tt_default_session_set( optImmediateSession );
if (tt_is_err( status )) {
clog << "ttsnoop: tt_default_session_set( \"";
clog << optImmediateSession << "\" ) = ";
clog << status << endl;
exit( 4 );
}
}
if (optImmediateTtOpen) {
int fd;
char *procid = ttdt_open( &fd, "Ttsnoop", "CDE",
globalVersionString, 1 );
DtTtSetLabel( dtb_ttsnoop_ttsnoop_win.ttsnoopWin_label,
"ttdt_open()", procid );
status = tt_ptr_error( procid );
if (tt_is_err( status )) {
char *statmsg = tt_status_message(status);
clog << "ttsnoop: ttdt_open() = ";
clog << status << ": " << statmsg << endl;
exit( 4 );
}
XtInputId id = XtAppAddInput( app, fd, (XtPointer)XtInputReadMask,
tttk_Xt_input_handler, procid );
DtTtCreated( DTTT_PROCID, procid, (void *)id );
if (optImmediateSnooping) {
Tt_pattern pat = tt_pattern_create();
tt_pattern_category_set( pat, TT_OBSERVE );
if (scopeFilesCount > 0) {
tt_pattern_scope_add( pat, TT_BOTH );
for (int i = 0; i < scopeFilesCount; i++) {
tt_pattern_file_add( pat, scopeFiles[i] );
}
} else {
tt_pattern_scope_add( pat, TT_SESSION );
}
char *sess = tt_default_session();
tt_pattern_session_add( pat, sess );
tt_free( sess );
for (int i = 0; i < opsCount; i++) {
tt_pattern_op_add( pat, ops[i] );
}
for (int i = 0; i < sendersCount; i++) {
tt_pattern_sender_add( pat, senders[i] );
}
if (vtype != 0) {
tt_pattern_arg_add( pat, TT_MODE_UNDEFINED,
vtype, 0 );
}
tt_pattern_callback_add( pat, justSnoopIt );
status = tt_pattern_register( pat );
DtTtSetLabel( dtb_ttsnoop_ttsnoop_win.ttsnoopWin_label,
"tt_pattern_register()", pat );
if (tt_is_err( status )) {
char *statmsg = tt_status_message(status);
clog << "ttsnoop: tt_pattern_register() = ";
clog << status << ": " << statmsg << endl;
exit( 4 );
}
DtTtCreated( DTTT_PATTERN, pat );
snoopPat = pat;
snoopPatIsRegistered = True;
}
}
if (snoopPat == 0) {
XtSetSensitive( dtb_ttsnoop_ttsnoop_win.
menubar_Snoop_item_Snoop_menu_items.Off_item, False );
}
DtTtSetLabel( dtb_ttsnoop_ttsnoop_win.
menubar_Snoop_item_Snoop_menu_items.Off_item,
snoopPatIsRegistered ? "Off" : "On" );
if (optMapOnOutput) {
XtVaSetValues( dtb_ttsnoop_ttsnoop_win.ttsnoopPane,
DtNmapOnOutput, optMapOnOutput, NULL );
}
installSignalHandler();
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/
/*
* Enter event loop
*/
XtAppMainLoop(app);
exit(0);
}
/**************************************************************************
*** DTB_USER_CODE_START
***
*** All automatically-generated data and functions have been defined.
***
*** Add new functions here, or at the top of the file.
***/
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/