cdesktopenv/cde/programs/ttsnoop/DtTt.C

747 lines
16 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 librararies 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: DtTt.C /main/4 1996/03/19 10:47:59 barstow $
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#if defined(linux)
#include <strstream>
#else
#include <strstream.h>
#endif
#include <Xm/TextF.h>
#include <Dt/SpinBox.h>
#include <Dt/HelpDialog.h>
#include "tt_c++.h"
#include "DtTt.h"
#include "messageProps_ui.h"
#include "patternProps_ui.h"
static const char ** dtTtProcids = 0;
static const void ** dtTtProcidClientDatums = 0;
static unsigned int dtTtProcidsCount = 0;
static Tt_pattern * dtTtPatterns = 0;
static unsigned int dtTtPatternsCount = 0;
static Tt_message * dtTtMessages = 0;
static unsigned int dtTtMessagesCount = 0;
static Tt_pattern ** dtTtDtSessions = 0;
static unsigned int dtTtDtSessionsCount = 0;
static Tt_pattern ** dtTtDtFiles = 0;
static unsigned int dtTtDtFilesCount = 0;
int _DtTtPatsNameKey = (int) (long) DtTtNth;
extern Tt_pattern snoopPat;
int
listGrow(
void ** pList,
unsigned int & listCount,
size_t elemSize
)
{
void *newList;
newList = realloc( *pList, (1 + listCount) * elemSize );
if (newList == 0) {
return 0;
}
*pList = newList;
listCount++;
return 1;
}
XmString
DtTtStatusString(
Tt_status status
)
{
char *s = tt_status_string( status );
XmString s2 = XmStringCreateLocalized( s );
tt_free( s );
return s2;
}
Tt_status
DtTtCreated(
DtTtType type,
const void * entity,
const void * clientData
)
{
Tt_status status = tt_ptr_error( entity );
if ((tt_is_err( status )) || (entity == 0)) {
return TT_OK;
}
switch (type) {
char *proc;
case DTTT_PROCID:
proc = strdup( (const char *)entity );
if (proc == 0) {
return TT_ERR_NOMEM;
}
if (! listAppend( dtTtProcids, dtTtProcidsCount, const char *,
proc ))
{
return TT_ERR_NOMEM;
}
dtTtProcidsCount--; // shared by both lists
if (! listAppend( dtTtProcidClientDatums, dtTtProcidsCount,
const void *, clientData ))
{
return TT_ERR_NOMEM;
}
break;
case DTTT_MESSAGE:
if (DtTtIndex( type, entity ) >= 0) {
return TT_OK;
}
if (! listAppend( dtTtMessages, dtTtMessagesCount, Tt_message,
(const Tt_message)entity ))
{
return TT_ERR_NOMEM;
}
break;
case DTTT_PATTERN:
if (DtTtIndex( type, entity ) >= 0) {
return TT_OK;
}
if (! listAppend( dtTtPatterns, dtTtPatternsCount, Tt_pattern,
(const Tt_pattern)entity ))
{
return TT_ERR_NOMEM;
}
break;
case DTTT_PTYPE:
case DTTT_OTYPE:
case DTTT_OBJECT:
case DTTT_SESSION:
case DTTT_DTSESSION:
case DTTT_DTFILE:
case DTTT_OP:
abort();
break;
}
return TT_OK;
}
Tt_status
DtTtCreated(
DtTtType type,
Tt_pattern * entity,
const char * name
)
{
if ((tt_is_err( tt_ptr_error( entity ) )) || (entity == 0)) {
return TT_OK;
}
if ((tt_is_err( tt_ptr_error( name ) )) || (name == 0)) {
return TT_OK;
}
switch (type) {
case DTTT_PROCID:
case DTTT_MESSAGE:
case DTTT_PATTERN:
case DTTT_PTYPE:
case DTTT_OTYPE:
case DTTT_OBJECT:
case DTTT_SESSION:
case DTTT_OP:
abort();
break;
case DTTT_DTSESSION:
tt_pattern_user_set( *entity, _DtTtPatsNameKey,
strdup( name ));
if (DtTtIndex( type, entity ) >= 0) {
return TT_OK;
}
if (! listAppend( dtTtDtSessions, dtTtDtSessionsCount,
Tt_pattern *, (Tt_pattern *)entity ))
{
return TT_ERR_NOMEM;
}
break;
case DTTT_DTFILE:
tt_pattern_user_set( *entity, _DtTtPatsNameKey,
strdup( name ));
if (DtTtIndex( type, entity ) >= 0) {
return TT_OK;
}
if (! listAppend( dtTtDtFiles, dtTtDtFilesCount,
Tt_pattern *, (Tt_pattern *)entity ))
{
return TT_ERR_NOMEM;
}
break;
}
while (*entity != 0) {
DtTtCreated( DTTT_PATTERN, *entity );
entity++;
}
return TT_OK;
}
void *
DtTtNth(
DtTtType type,
int n
)
{
switch (type) {
case DTTT_PROCID:
if ((n < 0) || (n >= dtTtProcidsCount)) {
return 0;
}
return (void *)dtTtProcids[ n ];
case DTTT_MESSAGE:
if ((n < 0) || (n >= dtTtMessagesCount)) {
return 0;
}
return dtTtMessages[ n ];
case DTTT_PATTERN:
if ((n < 0) || (n >= dtTtPatternsCount)) {
return 0;
}
return dtTtPatterns[ n ];
case DTTT_DTSESSION:
if ((n < 0) || (n >= dtTtDtSessionsCount)) {
return 0;
}
return dtTtDtSessions[ n ];
case DTTT_DTFILE:
if ((n < 0) || (n >= dtTtDtFilesCount)) {
return 0;
}
return dtTtDtFiles[ n ];
case DTTT_OP:
return tttk_op_string( (Tttk_op)(n+1) );
}
}
void *
DtTtNthClientDatum(
DtTtType type,
int n
)
{
switch (type) {
case DTTT_PROCID:
if ((n < 0) || (n >= dtTtProcidsCount)) {
return 0;
}
return (void *)dtTtProcidClientDatums[ n ];
default:
abort();
return 0;
}
}
void
DtTtNthClientDatumSet(
DtTtType type,
int n,
const void * clientData
)
{
switch (type) {
case DTTT_PROCID:
if ((n < 0) || (n >= dtTtProcidsCount)) {
return;
}
dtTtProcidClientDatums[ n ] = clientData;
return;
default:
abort();
}
}
int
DtTtIndex(
DtTtType type,
const void * entity
)
{
Tt_status status = tt_ptr_error( entity );
if ((tt_is_err( status )) || (entity == 0)) {
return -1;
}
switch (type) {
int i;
case DTTT_PROCID:
for (i = dtTtProcidsCount - 1; i >= 0; i--) {
if (strcmp( dtTtProcids[i], (char *)entity) == 0) {
return i;
}
}
return -1;
case DTTT_MESSAGE:
for (i = dtTtMessagesCount - 1; i >= 0; i--) {
if (dtTtMessages[i] == entity) {
return i;
}
}
return -1;
case DTTT_PATTERN:
for (i = dtTtPatternsCount - 1; i >= 0; i--) {
if (dtTtPatterns[i] == entity) {
return i;
}
}
return -1;
case DTTT_DTSESSION:
for (i = dtTtDtSessionsCount - 1; i >= 0; i--) {
if (dtTtDtSessions[i] == entity) {
return i;
}
}
return -1;
case DTTT_DTFILE:
for (i = dtTtDtFilesCount - 1; i >= 0; i--) {
if (dtTtDtFiles[i] == entity) {
return i;
}
}
return -1;
case DTTT_OP:
for (i = 1; i < TTDT_OP_LAST; i++) {
if (0 == strcmp( tttk_op_string( (Tttk_op)i ),
(char *)entity ))
{
return i;
}
}
return -1;
}
}
Tt_status
DtTtDestroyed(
DtTtType type,
const void * entity
)
{
Tt_status status = tt_ptr_error( entity );
if ((tt_is_err( status )) || (entity == 0)) {
return TT_OK;
}
switch (type) {
int i, j;
Tt_pattern *pats;
case DTTT_PROCID:
for (i = dtTtProcidsCount - 1; i >= 0; i--) {
if (strcmp( dtTtProcids[i], (char *)entity) == 0) {
break;
}
}
if (i < 0) {
return TT_WRN_NOTFOUND;
}
for (j = i; j < dtTtProcidsCount - 1; j++) {
dtTtProcids[j] = dtTtProcids[j+1];
}
for (j = i; j < dtTtProcidsCount - 1; j++) {
dtTtProcidClientDatums[j] =
dtTtProcidClientDatums[j+1];
}
dtTtProcidsCount--;
break;
case DTTT_MESSAGE:
for (i = dtTtMessagesCount - 1; i >= 0; i--) {
if (dtTtMessages[i] == entity) {
break;
}
}
if (i < 0) {
return TT_WRN_NOTFOUND;
}
for (j = i; j < dtTtMessagesCount - 1; j++) {
dtTtMessages[j] = dtTtMessages[j+1];
}
dtTtMessagesCount--;
break;
case DTTT_PATTERN:
if (snoopPat == entity) snoopPat = 0;
for (i = dtTtPatternsCount - 1; i >= 0; i--) {
if (dtTtPatterns[i] == entity) {
break;
}
}
if (i < 0) {
return TT_WRN_NOTFOUND;
}
for (j = i; j < dtTtPatternsCount - 1; j++) {
dtTtPatterns[j] = dtTtPatterns[j+1];
}
dtTtPatternsCount--;
break;
case DTTT_DTSESSION:
for (i = dtTtDtSessionsCount - 1; i >= 0; i--) {
if (dtTtDtSessions[i] == entity) {
break;
}
}
if (i < 0) {
return TT_WRN_NOTFOUND;
}
pats = (Tt_pattern *)entity;
while (*pats != 0) {
DtTtDestroyed( DTTT_PATTERN, *pats );
pats++;
}
for (j = i; j < dtTtDtSessionsCount - 1; j++) {
dtTtDtSessions[j] = dtTtDtSessions[j+1];
}
dtTtDtSessionsCount--;
break;
case DTTT_DTFILE:
for (i = dtTtDtFilesCount - 1; i >= 0; i--) {
if (dtTtDtFiles[i] == entity) {
break;
}
}
if (i < 0) {
return TT_WRN_NOTFOUND;
}
pats = (Tt_pattern *)entity;
while (*pats != 0) {
DtTtDestroyed( DTTT_PATTERN, *pats );
pats++;
}
for (j = i; j < dtTtDtFilesCount - 1; j++) {
dtTtDtFiles[j] = dtTtDtFiles[j+1];
}
dtTtDtFilesCount--;
break;
}
return TT_OK;
}
Tt_status
DtTtSetLabel(
Widget labelWidget,
const char *string
)
{
if (labelWidget == 0) {
return TT_OK;
}
XmString labelXmString = XmStringCreateLocalized( (String)string );
XtVaSetValues( labelWidget, XmNlabelString, labelXmString, 0 );
XmStringFree( labelXmString );
return TT_OK;
}
Tt_status
DtTtSetLabel(
Widget labelWidget,
const char *func,
void *val
)
{
Tt_status status = tt_ptr_error( val );
ostrstream errStream;
errStream << func << " = " << val << " (" << status << ")" << ends;
char *label = errStream.str();
DtTtSetLabel( labelWidget, label );
delete label;
return status;
}
Tt_status
DtTtSetLabel(
Widget labelWidget,
const char *func,
Tt_status status
)
{
ostrstream errStream;
errStream << func << " = " << status << ends;
char *label = errStream.str();
DtTtSetLabel( labelWidget, label );
delete label;
return status;
}
int
DtTtSetLabel(
Widget labelWidget,
const char *func,
int returnVal
)
{
ostrstream errStream;
errStream << func << " = " << returnVal << ends;
char *label = errStream.str();
DtTtSetLabel( labelWidget, label );
delete label;
return returnVal;
}
static XmString *
_DtTtChoices(
Tt_pattern ** pPats,
int count
)
{
// XXX when to free?
XmString *items = (XmString *)XtMalloc( count * sizeof( XmString ));
if (items == 0) {
return 0;
}
for (int i = 0; i < count; i++) {
ostrstream itemStream;
itemStream << (void *)pPats[ i ];
char *name = (char *)
tt_pattern_user( *pPats[ i ], _DtTtPatsNameKey );
if (! tt_is_err( tt_ptr_error( name ))) {
itemStream << " " << name;
tt_free( name );
}
itemStream << ends;
char *string = itemStream.str();
items[ i ] = XmStringCreateLocalized( string );
delete string;
}
return items;
}
XmString *
_DtTtChoices(
DtTtType type,
int * itemCount
)
{
*itemCount = 0;
switch (type) {
XmString *items;
int i;
int opCount;
case DTTT_PROCID:
items = (XmString *)
XtMalloc( dtTtProcidsCount * sizeof( XmString ));
if (items == 0) {
return 0;
}
*itemCount = dtTtProcidsCount;
for (i = 0; i < dtTtProcidsCount; i++) {
items[ i ] = XmStringCreateLocalized(
(String)dtTtProcids[ i ] );
}
return items;
case DTTT_MESSAGE:
items = (XmString *)
XtMalloc( dtTtMessagesCount * sizeof( XmString ));
if (items == 0) {
return 0;
}
*itemCount = dtTtMessagesCount;
for (i = 0; i < dtTtMessagesCount; i++) {
ostrstream itemStream;
itemStream << (void *)dtTtMessages[ i ];
char *op = tt_message_op( dtTtMessages[ i ] );
if (! tt_is_err( tt_ptr_error( op ))) {
itemStream << " " << op;
tt_free( op );
}
char *id = tt_message_id( dtTtMessages[ i ] );
if (! tt_is_err( tt_ptr_error( id ))) {
itemStream << " " << id;
tt_free( id );
}
itemStream << ends;
char *string = itemStream.str();
items[ i ] = XmStringCreateLocalized( string );
delete string;
}
return items;
case DTTT_PATTERN:
items = (XmString *)
XtMalloc( dtTtPatternsCount * sizeof( XmString ));
if (items == 0) {
return 0;
}
*itemCount = dtTtPatternsCount;
for (i = 0; i < dtTtPatternsCount; i++) {
ostrstream itemStream;
itemStream << (void *)dtTtPatterns[ i ] << ends;
items[ i ] = XmStringCreateLocalized(
itemStream.str() );
delete itemStream.str();
}
return items;
case DTTT_DTSESSION:
*itemCount = dtTtDtSessionsCount;
return _DtTtChoices( dtTtDtSessions, dtTtDtSessionsCount );
case DTTT_DTFILE:
*itemCount = dtTtDtFilesCount;
return _DtTtChoices( dtTtDtFiles, dtTtDtFilesCount );
case DTTT_OP:
// XXX when to free? ditto for each case
opCount = ((int)TTDT_OP_LAST) - 1;
items = (XmString *)
XtMalloc( opCount * sizeof( XmString ));
if (items == 0) {
return 0;
}
*itemCount = opCount;
for (i = 1; i <= opCount; i++) {
items[ i-1 ] = XmStringCreateLocalized(
(String)tttk_op_string( (Tttk_op)i ));
}
return items;
}
}
#if defined(aix)
#define AIX_CONST_STRING (char *)
#else
#define AIX_CONST_STRING
#endif
void
_DtOpen(
Widget label,
const char * cmd,
const char * tempnamTemplate
)
{
char *file = tempnam( 0, AIX_CONST_STRING tempnamTemplate );
ostrstream cmdStream;
cmdStream << cmd << " > " << file << ends;
int sysStat = system( cmdStream.str() );
if (! WIFEXITED( sysStat )) {
ostrstream func;
func << "system( \"" << cmdStream.str() << "\" )" << ends;
DtTtSetLabel( label, func.str(), sysStat );
delete cmdStream.str();
delete func.str();
return;
}
if (WEXITSTATUS( sysStat ) != 0) {
DtTtSetLabel( label, cmdStream.str(), WEXITSTATUS( sysStat ));
delete cmdStream.str();
return;
}
delete cmdStream.str();
_DtOpen( label, file );
}
void
_DtOpen(
Widget label,
const char * file
)
{
ostrstream labelStream;
labelStream << "dtaction Open " << file << ends;
DtTtSetLabel( label, labelStream.str() );
delete labelStream.str();
ostrstream cmd;
cmd << "( unset TT_TRACE_SCRIPT; if dtaction Open " << file
<< "; then :; else textedit " << file << "; fi; sleep 600; rm -f "
<< file << " ) &" << ends;
system( cmd.str() );
delete cmd.str();
}
void
_DtOpen(
Widget label,
void * buf,
size_t len,
const char * tempnamTemplate
)
{
char *file = tempnam( 0, AIX_CONST_STRING tempnamTemplate );
int fd = open( file, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR );
if (write( fd, buf, len ) < 0) {
DtTtSetLabel( label, file, errno );
return;
}
close( fd );
_DtOpen( label, file );
}
void
_DtMan(
Widget label,
const char * topic
)
{
ostrstream labelStream;
labelStream << "dtaction Dtmanpageview " << topic << ends;
DtTtSetLabel( label, labelStream.str() );
delete labelStream.str();
ostrstream cmd;
cmd << "unset TT_TRACE_SCRIPT; if dtaction Dtmanpageview " << topic
<< "; then :; else cmdtool -c man " << topic << "; fi &" << ends;
system( cmd.str() );
delete cmd.str();
}
Boolean
_DtCanHelp(
const char *topics
)
{
if (topics == 0) return False;
if (strchr( topics, ' ' ) != 0) {
// Must not be a list of man pages
return False;
}
return True;
}
Boolean
_DtHelped(
Widget helpDialog
)
{
char *topics;
XtVaGetValues( helpDialog, DtNstringData, &topics, 0 );
if (! _DtCanHelp( topics )) {
return False;
}
char *newTopics = strdup( topics );
const char *whiteSpace = "(12345689) \t:-,.*\n";
const char *topic = strtok( newTopics, whiteSpace );
while (topic != 0) {
_DtMan( 0, topic );
topic = strtok( 0, whiteSpace );
}
free( newTopics );
return True;
}