cdesktopenv/cde/lib/tt/bin/tttrace/tttrace_objs.C

446 lines
8.9 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
//%% (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;
_form = NO_FORM;
for(int i = 0; i < MAXARGS; i++) {
_cargv[i] = NULL;
}
}
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;
}