[Contents] [Prev. Chapter] [Next Section] [Index] [Help]

A    Example Source Files

This appendix provides listings for the following source files

All source files are available online in the directory $FUSE_TOP/rundata/examples/EnCASE once FUSE EnCASE is installed. The source files for the minigrep example are in the minigrep directory and the source files for the dxdiff example are in the dxdiff directory. Refer to the README text file in the dxdiff directory for more information about the dxdiff example. The listings in this appendix are for Digital UNIX. The source files are slightly different for different platforms. Check the $FUSE_TOP/rundata/examples/EnCASEdirectory for source files specific to your platform.

Note

The dxdiff example does not work on Sun systems because there is no equivalent dxdiff utility on Sun.


[Contents] [Prev. Chapter] [Next Section] [Index] [Help]

A.1    Source Files for minigrep Example

Example A-1 is the complete header file for the minigrep example.

Example A-1: minigrep Header File

/*
** minigrep.h
**
**  Header file for
**
**  Minigrep: An example tool that can be integrated with FUSE using
**  FUSE EnCASE
*/
/* $Id: DOCU_008.HTM,v 1.1 1997/05/07 13:33:15 catano Exp $
*/

/*
 *
 * Copyright (c) 1991
 * Digital Equipment Corporation
 * All rights reserved.
 *
 * This software is furnished under a license and may be used and
 * copied  only  in accordance with the terms of such license and
 * with the  inclusion  of  the  above  copyright  notice.   This
 * software  or  any  other copies thereof may not be provided or
 * otherwise made available to any other person.  No title to and
 * ownership of the software is hereby transferred.
 *
 * The information in this software is subject to change  without
 * notice  and should not be construed as a commitment by Digital
 * Equipment Corporation.
 *
 * Digital assumes no responsibility for the use  or  reliability
 * of its software on equipment which is not supplied by Digital.
 *
*/

 /*********************** INCLUDE files *************************/

#include <stdio.h>
#include <string.h>

/*  types.h is needed to use the FD_SET, FD_ZERO, etc. macros for use on
**  file descriptor (thus, FD) bitmasks for use with the select system
**  call.
*/
#include <sys/types.h>
#include "fuse.h"

/*  time.h is needed to use the timeval struct that allows the build
**  a timeout interval for the `select' system call we use to determine
**  if there is any input available on the file descriptors to be read
**  (for example, stdin, grep, and/or FUSE's message file descriptor).
*/
#include <sys/time.h>

/*  FUSE_INTEGRATION use of minigrep requires the function prototypes
**  that the TIL compiler created in FUSE_MINIGREP.h
*/
#ifdef FUSE_INTEGRATION
#include "FUSE_MINIGREP.h"
#endif

/***************************** MACRO Definitions *************************/

/*
**  MAX_EXPRESSION_LENGTH is the maximum allowable size of the
**  search and file expressions that will be allowed in the call
**  to grep.
*/
#define MAX_EXPRESSION_LENGTH 60

/*
**  MAX_COMMAND_LENGTH is the maximum allowable size of the grep command
**  line passed to the pipe to be executed
*/
#define MAX_COMMAND_LENGTH 128

/*  MAX_RETURN_LENGTH is the maximum allowable size of the lines written
**  out by grep.
*/
#define MAX_RETURN_LENGTH 256

/******************** GLOBAL Variables (standalone use) ***********/

/**** GLOBAL Strings *****/

/*  char matchExp[MAX_EXPRESSION_LENGTH] is used to store the expression
**  to be matched with `grep -n'
*/
static char matchExp[MAX_EXPRESSION_LENGTH];

/*  char fileExp[MAX_EXPRESSION_LENGTH] is used to store the expression
**  of the files to be searched with `grep -n'
*/
static char fileExp[MAX_EXPRESSION_LENGTH];

/**** GLOBAL State Information ****/

/*  The state diagram for minigrep looks like this:
**
**     start --------> running ------> getFileExp -----> processing
**                        |   ^                                  |
**                        |   |                                  |
**                        |   -----------------------------------
**                        |
**                        v
**                    stopping
*/

/*  States is an enumerated type for the allowable states.  */
enum States {start, running, getFileExp, processing, stopping };

/*  currentState stores the current state (as an int since it's set using
**   the enumerated type).  */
static int currentState = start;

/*  stateNames is an array of strings that correspond to the values
**  enumerated in States.  */
static char *stateNames[5] = { "start", "running", "getFileExp",
                               "processing", "stopping" };

/**** GLOBAL information about the expansion of fileExp ****/

/*  int NumberOfFiles is used to indicate how may files match
**  the file expression.  Only of real importance in the special
**  case when the file expression expands to only 1 file.
*/ static int NumberOfFiles=0;

/*  SingleFile is used in the special case where grep will
**  only be searching a single file.  If this is the case, it stores
**  the name of the single file being searched so it can be prepended
**  to the output of grep.
*/
static char SingleFile[MAX_EXPRESSION_LENGTH];

/**** GLOBAL information about file descriptors, streams, and sockets ****/

/*  fd_set (set of file descriptors) is defined in types.h
**  readFDS is used as the mask of the file descriptors to be checked for
**  reading.
*/
static fd_set readFDS;

/*  stdinFD is the file descriptor of the stdin stream (0).  Any stream's
**  file descriptor can be determined by looking at the _file
**  field of the FILE structure.  (Look at stdio.h for the structure
**  layout)
**  This value is initialed in doStartState();
*/
static int stdinFD;

/*  FILE *grepStream;    is a file pointer to the stream opened
**  (with popen) to process the grep command built from
**  `grep -n' `matchExp' and`fileExp'
*/
/*  int grepFD; is the file descriptor of the grepStream that has
**  been opened.  Then, we can `select' on that file descriptor when
**  it is open.
**  -1 means not open (don't `select' on it) otherwise, select on the
**  value.
*/
static FILE *grepStream;
static int grepFD = -1;

/*  int grepStreamOpen;
**  0 means the grepStream (opened with popen) is NOT open.
**  1 means the grepStream is open.
*/
static int grepStreamOpen = 0;

/******************** GLOBAL Variables (FUSE Integration Use) *******/

#ifdef FUSE_INTEGRATION

/**** GLOBAL function pointers ****/

/* void (*toolMessageHandler)() is the function to be called (with no
** arguments) whenever there is a message on the toolFD to be handled.
** One can determine if there is a message on the file dscriptor using a
** select system call with the proper bit mask (i.e., a bit mask with the
** bit for the value of toolFD set).
** This is pointer is set to the address of the actual function to call
** when FUSE_Init calls back to our registration function.
*/
static void (*toolMessageHandler)();

/**** GLOBAL file descriptor and status variables ****/

/* toolFD is the file descriptor of the socket that is connected to
** the  FUSE Message Server
*/
static int toolFD;

/*  editorReady is used to store 0 if the FUSE Editor has been initialized
**  (i.e., completely started up) for the current minigrep command.
**  This variable is set to 1 (in the editorDone() callback) if the FUSE
**  Editor has been initialized.
**  This variable is set to 0 upon entering the "running" state to
**  force the editor to be initialized for each minigrep command (to
**  exercise the callback).
*/
static int editorReady = 0;

#endif

The complete C source file for the minigrep example is in Example A-2 and Example A-3.

Example A-2: minigrep C Source File, Part 1 of 2

/*   See Example A-3 for Part 2 of the minigrep C source file */

/***********************************************************************/

** minigrep.c
**
**  Minigrep: An example tool that can be integrated with FUSE using
**  FUSE EnCASE
*/

/*  $Id: DOCU_008.HTM,v 1.1 1997/05/07 13:33:15 catano Exp $
*/

/*
 *
 * Copyright (c) 1991
 * Digital Equipment Corporation
 * All rights reserved.
 *
 * This software is furnished under a license and may be used and
 * copied  only  in accordance with the terms of such license and
 * with the  inclusion  of  the  above  copyright  notice.   This
 * software  or  any  other copies thereof may not be provided or
 * otherwise made available to any other person.  No title to and
 * ownership of the software is hereby transferred.
 *
 * The information in this software is subject to change  without
 * notice  and should not be construed as a commitment by Digital
 * Equipment Corporation.
 *
 * Digital assumes no responsibility for the use  or  reliability
 * of its software on equipment which is not supplied by Digital.
 *
*/
/*
**  This program uses `grep' in a very simple (and constrained) manner.
**  The user is prompted for a single match expression to be located
**  and a single file expression to be searched.
**  These expressions are then used with a popen call to grep
**  (with the -n option to get the line number).  The results of the
**  grep are written to the terminal and, when integrated with
**  FUSE, the lines found are shown/highlighted in the FUSE Editor
**  (at the rate of 1 line every 3 seconds due a sleep(3) inserted).
**
**  A main purpose of the body of this tool is to `normalize' the grep
**  output since it appears that grep output ONLY prefixes
**  the line with the source file name if the file
**  expression expands to include more than 1 file.  This program
**  traps that situation and adds the source filename as
**  a prefix to the grep output line.
**
**  This program has can be built as a standalone OR as a FUSE-aware
**  tool.  Compiling without the FUSE_INTEGRATION defined
**  (as in make minigrep), results in a tool that can be run
**  on a stdin/stdout terminal.  Compiling with the
**  FUSE_INTEGRATION flag set (as in make fuse_minigrep)
**  results in a tool that is integrated into FUSE.  See
**  the Makefile for details.
*/

/*  The state diagram for minigrep looks like this:
**
**   start --------> running ------> getFileExp -----> processing
**                      |   ^                                  |
**                      |   |                                  |
**                      |   -----------------------------------
**                      |
**                      v
**                  stopping
*/

#include "minigrep.h"

/*************  forward declarations/prototypes **********************/
/*  The main flow of control */
void main();
void doStartState();
void doRunningState();
void doFileExpState();
void doProcessingState();
void doStoppingState();

/*  Utility routines */
void changeState(int newState);
void getStdin(char *output);
void selectFD();
void countSearchItems(char *fileExpression);
void readGrepStream();
void normalizeGrepOutput(char *string);

/*  FUSE-related routines */
#ifdef FUSE_INTEGRATION
void fuseRegistration( int socket_id, void (*fuseMsgHandler)() );
void editorDone(void *passedIn, char *reply);
#endif

/**********************************************************************/
/*
** void main()
*/

void main()
{
  void selectFD();

   doStartState();

   while ( currentState != stopping ) {
    selectFD();

#ifdef FUSE_INTEGRATION
    if ( FD_ISSET(toolFD, &readFDS) ) {
      toolMessageHandler();
    }
#endif
    switch ( currentState ) {
    case running :
      doRunningState();
      break;
    case getFileExp :
      doFileExpState();
      break;
    case processing :
      doProcessingState();
      break;
    }
  }
  doStoppingState();
}

/*********************************************************************/

/*  void doStartState()
**
**  initializes the minigrep application.
*/

void doStartState()
{
#ifdef FUSE_INTEGRATION
  int fuseInit;
#endif

  /*  initialize the value of the stdinFD */
  stdinFD = stdin->_file;

#ifdef FUSE_INTEGRATION
 /* initialize FUSE messaging environment */
  fuseInit = FUSE_init( fuseRegistration );
  if ( fuseInit != 0 ) {
    printf("\enFUSE_init failed.  Messaging is not possible.");
    changeState(stopping);
  }
#endif
  changeState(running);
}
/**********************************************************************/

/*  void doRunningState()
**
**  gets the match expression the user types in.
*/

void doRunningState()
{
  void getStdin(char *);

#ifdef FUSE_INTEGRATION
  editorReady = 0;
#endif

  if ( FD_ISSET(stdinFD, &readFDS) ) {
    getStdin(matchExp);
    if ( !strcmp(matchExp, "q") || !strcmp(matchExp, "Q") ) {
      changeState(stopping);
      return;
    }
    else if ( !strcmp(matchExp, "") ) {
      return;
    }
    else {
      changeState(getFileExp);
      return;
    }
  }
}

/**********************************************************************/

/*  void doFileExpState()
**
**  gets the user input for the expression of files to be searched
with
**  `grep -n'
**
*/

void doFileExpState()
{
  void getStdin(char *);
  if ( FD_ISSET(stdinFD, &readFDS) ) {
    getStdin(fileExp);
    if ( !strcmp(fileExp, "") ) {
      return;
    }
    else {
      countSearchItems(fileExp);
      changeState(processing);
      return;
    }
  }
}

/**********************************************************************/

/*  void doProcessingState()
**
**  processes `grep -n' with the strings provided in
**  the previous 2 states.
*/

void doProcessingState()
{
  static char grepExp[]="grep -n";
  char grepLine[MAX_COMMAND_LENGTH];

  if ( !grepStreamOpen ) {
    sprintf(grepLine, "%s %s %s", grepExp, matchExp, fileExp);
    printf("Processing \e"%s\e"...\en", grepLine);
    fflush(stdout);
   /*  popen stream for processing of command */
    if ( (grepStream = popen(grepLine, "r")) == NULL ) {
      perror("Unable to open stream for processing.  Exiting.");
      changeState(stopping);
      return;
    }
    else {
      grepStreamOpen = 1;
      grepFD = grepStream->_file;
#ifdef FUSE_INTEGRATION
      printf("\enWaiting for the Editor...\n\n");
      FUSE_SEND_EditorOpenFile(editorDone, NULL, "");
#endif
    }
  }
  else
#ifdef FUSE_INTEGRATION
  if ( editorReady )
#endif
  {
    readGrepStream();
    if ( !grepStreamOpen ) {
      changeState(running);
    }
  }
}

/**********************************************************************/

void doStoppingState()
{
#ifdef FUSE_INTEGRATION
  FUSE_SEND_ToolControlNotification("STOP");
#endif
}

/****************************************************************************/
/*  void changeState(int newState)
**
**  changes the value of the currentState global variable to the new state
**  and sends a FUSE_state_change message initiating the state change.
*/

void changeState(int newState)
{
  if ( newState == running ) {
   printf("\enAt the prompt, please enter a match expression (to be located)");
   printf("\en\etand a file-expression (file(s) to be searched)...");
   printf("\enmatch expression <q to quit>: ");
  }
  else if ( newState == getFileExp ) {
    printf("file expression: ");
  }
  fflush(stdout);

  currentState = newState;
#ifdef FUSE_INTEGRATION
  FUSE_state_change(stateNames[newState]);
#endif
}

/***********************************************************************/

/*   See Example A-3 for Part 2 of the minigrep C source file */

Example A-3: minigrep C Source File, Part 2 of 2

/*   See Example A-2 for Part 1 of the minigrep C source file */

/***********************************************************************/

/*  void getStdin(char *output)
**
**  This function is called when there is input pending on the stdinFD.
**  It reads from stdin until a newline (\n) is read, putting the string
**  that is read into the output character array.
*/
void getStdin(char *output)
{
  char c;
  int i=0;

  while ( read(stdinFD, &c, 1), c != `\n' ) {
    output[i++]=c;
  }
  output[i]=NULL;
}

/*************************************************************************/

/*  void selectFD()
**
**  looks at the appropriate file descriptors to determine if
**  input is available.
*/

void selectFD()
{
  int numFilesReady;   /* the number of file descriptors ready to be */
                        /* processed.  Returned from call to select. */
                       /* */
  struct timeval timeout;  /* a timeval structure (defined in
                        ** <sys/time.h> used to timeout the select
                        ** after .5 seconds
                        */

  timeout.tv_sec = 0;
  timeout.tv_usec = 500;

/*
** FD_SET (defined in types.h) sets the proper bit in the readFDS (file
** descriptor set) so any system calls to select will know to look for
** possible input on the file desriptors.  Since the args to select are
** modified in place, re-initialize readFDS each time so the select looks
** for input on both the toolFD and the stdinFD.
**
** We always need stdinFD.  We need toolFD only if we're
** integrating with FUSE and need to listen to its message server.
*/
/* initialize the file descriptor mask */
  FD_ZERO(&readFDS);

  FD_SET(stdinFD, &readFDS);

/*  Look for activity on the grepFD when it is open (i.e., >= 0)
*/
  if ( grepFD >= 0) {
    FD_SET(grepFD, &readFDS);
  }

#ifdef FUSE_INTEGRATION
  FD_SET(toolFD, &readFDS);
#endif

/* Use select system call to listen to the file descriptor(s).
** MAXSELFD is defined in types.h and specifies the maximum number of
** file desriptors that can exist.  We use this as the limit of file
** descriptors on which to look for input.
*/

  numFilesReady = select(MAXSELFD, &readFDS, 0, 0, &timeout);

  if ( numFilesReady < 0 ) {
    printf("\enSELECT returned with an error condition.  Shutting down.");
    changeState(stopping);
    return;
  }
}

/************************************************************************/

/*
**  void countSearchItems(char* fileExpression)
**
**  Uses fileExpression as file description and counts the number of items
**  that match the description.
**  It is a special case to grep against one item (since that prevents the
**  item's file name in the grep output).  So when the count is equal to 1,
**  the global variable, SingleFile, is set to that one item.  Otherwise,
**  SingleFile is set to NULL.
*/
void countSearchItems(char* fileExpression)
{
  char lsLine[MAX_COMMAND_LENGTH];
  FILE* lsStream;
  char returnString[MAX_RETURN_LENGTH];
  int i=0;
  int length;

  sprintf(lsLine, "ls %s", fileExpression);

/*  popen stream for processing of command */
  if ( (lsStream = popen(lsLine, "r")) == NULL ) {
    perror("Unable to open stream for processing.  Exiting");
    return;
  }

/*  Read stream and parse returned strings */
  while ( fgets(returnString, MAX_RETURN_LENGTH, lsStream) != NULL ) {
    i++;
    /* the carriage return/linefeed chars need to get stripped off.
*/
    length = strlen(returnString);
    returnString[length-1] = NULL;
    returnString[length] = NULL;
  }

/*  Close the stream  */
  pclose(lsStream);

/*  If i = 1, then set SingleFile.  Otherwise NULL out SingleFile.
*/
  if ( i == 1 ) {
    NumberOfFiles = 1;
    strcpy(SingleFile, returnString);
  }
  else {
    NumberOfFiles = i;
    SingleFile[0] = NULL;
  }
  return;
}

/********************************************************************/
/*
**  void readGrepStream()
**
**  reads the grepStream for a line of output.  Normalizes it with
**  a call to normalizeGrepOutput()
*/

void readGrepStream()
{
  char returnString[MAX_RETURN_LENGTH];

  if ( fgets(returnString, MAX_RETURN_LENGTH, grepStream) != NULL ) {
    normalizeGrepOutput(returnString);
  }
  else {
    pclose(grepStream);
    grepStreamOpen = 0;
    grepFD = -1;
  }
}

/****************************************************************************/

/*
**  void normalizeGrepOutput(char* string)
**
**  If the (global variable) NumberOfFiles = 1,
**  write out the value of (global variable) SingleFile to outputString,
**  and concatenate ":" and value of string on the end.
**  Otherwise, use string unaltered.
**
**  When integrated with FUSE, step through the lines that were found
**  at a rate of 1 line every 5 seconds.
**
*/
void normalizeGrepOutput(char* string)
{
  char outputString[MAX_RETURN_LENGTH];
  char fileName[MAX_RETURN_LENGTH];
  char lineString[MAX_EXPRESSION_LENGTH];
  int lineNumber;
  char fullPathName[MAX_RETURN_LENGTH];
  void selectFD();

  if ( NumberOfFiles == 1 ) {
    sprintf(outputString, "%s:%s", SingleFile, string);
  }
  else {
    sprintf(outputString, "%s", string);
  }
  printf("%s", outputString);

#ifdef FUSE_INTEGRATION
  { /* This block gets the file name and line number from outputString */
    char c;
    int i,j;

    i = j = 0;
    while ( (c = outputString[i]) != `:' ) {
      fileName[j++] = outputString[i++];
    }
    fileName[j++] = NULL;
    i++;
    j = 0;
    while ( (c = outputString[i]) != `:' ) {
      lineString[j++] = outputString[i++];
    }
    lineString[j++] = NULL;
    lineNumber = atoi(lineString);
  }
  /* FUSE Editor needs full path name so append working directory path
  ** unless the user entered a file expression that starts with a
  ** slash "/"
  */
  if (string[0] != `/') {
    getwd(fullPathName);
    strcat(fullPathName, "/");
    strcat(fullPathName, fileName);
  }
  else {
    strcpy(fullPathName, fileName);
  }

  /* If Editor doesn't have fullPathName in its buffer, get it.
  ** If Editor does have fullPathName in its buffer, this message
  ** is ignored.  (Minimizing the number of these calls would
  ** be better, however.)
  */
  FUSE_SEND_EditorOpenFile(NULL, NULL, fullPathName);

  /* Goes to the given lineNumber in the buffer.  */
  FUSE_SEND_EditorGotoLine(NULL, NULL, "line", lineNumber);
  sleep(3);

#endif
}

/***********************************************************************/
/*  void fuseRegistration( int socket_id, void (*fuseMsgHandler)()
)
**
**  This function is the function passed to the required call to FUSE_init.
**  The call to FUSE_init calls this function to associate the FUSE message
**  server to minigrep's incoming message-handling routine.
**
**  Applications that are based on Motif or the X Toolkit need to call
**  XtAddInput() or XtAppAddInput() to register the socket_id in the Xt
**  layer.
**
**  Since minigrep is NOT based on Motif or the X Toolkit, the socket_id
**  must be monitored (the file descriptor will be used for the
**  minigrep tool in the `select' system call) and fuseMsgHandler()
**  will be called when incoming data appears on the socket.
*/

#ifdef FUSE_INTEGRATION

void fuseRegistration( int socket_id, void (*fuseMsgHandler)() )
{
  toolFD = socket_id;
  toolMessageHandler = fuseMsgHandler;
}

#endif

/***********************************************************************/

/* void editorDone(void *passedIn, char *reply)
**
** is provided as a callback to FUSE_SEND_Editor... messages.
** Its purpose is to set the value of editorReady to 1.
*/

#ifdef FUSE_INTEGRATION
void editorDone(void *passedIn, char *reply)
{
/*  To see the callback working, uncomment thenext statement  */
/*  printf("\enInside editorDone() callback: state = <%s>, reply = <%s>", */
/*         stateNames[currentState], reply); */
  editorReady = 1;
/*
** Note that the specified reply needs to be freed since the FUSE
**      Message Server does not free it up automoatically.
*/
  free(reply);
}

#endif

/*
**  void FUSE_RECV_ToolControlCommand(char *command, char *param)
**
**  This function implements the procedure to be executed when a
**  ToolControlCommand is sent to the Minigrep tool.  At this time, the
**  only reason this message is sent to request a tool to "STOP".
**  At this time, the `param' parameter is not used though its use is
**  reserved for possible later use.
**  The message, ToolControlCommand, is a message that all FUSE tools are
**  required to receive.  The message is specified in
**  $(FUSE_TOP)/rundata/schema/message_lib.msg.
**  A tool receives this message when the user has indicated from the
**  control panel (or other non-local source) that the tool should
**  be stopped.  The tool integrator is required to write the body of
**  this function in order to specify the behavior that should happen
**  when the tool needs to stop.  At the very least, the tool needs to
**  tell the control panel it is stopping (by a
**  ToolControlNotification("STOP") message) and then exiting the tool.
**  If desired, the tool can execute some cleanup procedure before sending
**  the "STOP" message.  The body of this function should execute that
**  cleanup behavior if it is desired.
*/
#ifdef FUSE_INTEGRATION
void FUSE_RECV_ToolControlCommand(char *command, char *param)
{
  printf("\en\enMinigrep received ToolControlCommand(\e"%s\e", \e"%s\e")...",
         command, param);
  if ( !strcmp(command, "STOP") ) {
    printf("\enExiting...");
    fflush(stdout);
    FUSE_SEND_ToolControlNotification("STOP");
    sleep(3);
    exit();
  }
}
#endif


[Contents] [Prev. Chapter] [Prev. Section] [Index] [Help]

A.2 Files for Script Interface Example

The example files for integrating dxdiff for the script interface are Example A-4 for the source code, Example A-5 for the TIL file, and Example A-6 for the example makefile.

Example A-4: Example Source File for Script Interface

#!/bin/sh
#
#  dxdiffScript
#
#  $Id: DOCU_008.HTM,v 1.1 1997/05/07 13:33:15 catano Exp $
#
#  This is a (/bin/sh) script to integrate the use of the dxdiff (DECwindows
#       visual differences program) into FUSE.
#
#
# *
# * Copyright (c) 1991
# * Digital Equipment Corporation
# * All rights reserved.
# *
# * This software is furnished under a license and may be used and
# * copied  only  in accordance with the terms of such license and
# * with the  inclusion  of  the  above  copyright  notice.   This
# * software  or  any  other copies thereof may not be provided or
# * otherwise made available to any other person.  No title to and
# * ownership of the software is hereby transferred.
# *
# * The information in this software is subject to change  without
# * notice  and should not be construed as a commitment by Digital
# * Equipment Corporation.
# *
# * Digital assumes no responsibility for the use  or  reliability
# * of its software on equipment which is not supplied by Digital.
# *

# Turn off extraneous fusescript messages...
fusescript -info off

# Uncomment the following line for verbose script processing
### set -v

echo "dxdiff starting..."
bgProcess=0
triggered=1

##
## Now that dxdiff has been started, change to the "running" state.
## The running state is the state that will receive any trigger messages
## that could have started this tool.
##
stateName="running"
fusescript -state "running"

while (test "$stateName" != "done" )
do
    dxdiffMessage=`fusescript -recv 0`
    dxdiffStatus=$?
###
###  Trap Messages and react.  Messages we can expect are:
###  1) ToolControlCommand "STOP" (action: cleanup and exit)
###  2) CompareRcsVersions <filename> <v1> <v2> (action: dxdiff the 2 vers.)
###
    if test "$dxdiffStatus" -eq 0
    then
        echo "Message =>" $dxdiffMessage
        dxdiffMessageType=`echo $dxdiffMessage | awk `{print $2}'`
        dxdiffMessageParam1=`echo $dxdiffMessage | awk `{print $3}'`
        if test "$dxdiffMessageType" = "ToolControlCommand" -a \e
                "$dxdiffMessageParam1" = "STOP"
        then
            echo "dxdiff received a STOP command!"
            stateName="exiting"
            fusescript -state "exiting"
        elif test "$dxdiffMessageType" = "CompareRcsVersions"
        then
            triggered=0
            echo "Received a CompareRcsVersions message"
            dxdiffVers1=`echo $dxdiffMessage | awk `{print $4}'`
            dxdiffVers2=`echo $dxdiffMessage | awk `{print $5}'`
            fileName1=`echo $dxdiffMessageParam1$dxdiffVers1`
            fileName2=`echo $dxdiffMessageParam1$dxdiffVers2`
            ### check out the 2 files to /tmp with modified names
            co -p$dxdiffVers1 $dxdiffMessageParam1 > /tmp/$fileName1
            co -p$dxdiffVers2 $dxdiffMessageParam1 > /tmp/$fileName2
            ### set the File1 and File2 variables used in the execDxdiff state
            File1=/tmp/$fileName1
            File2=/tmp/$fileName2
###         echo "File1=>" $File1 "    File2=>" $File2
            stateName="execDxdiff"
            fusescript -state "execDxdiff"
        fi
    fi
###
    case $stateName in
        running)        echo -n "Filename 1: "
                        read File1
                        if ( test $File1 )
                        then
                            stateName="getFile2"
                            fusescript -state "getFile2"
                        else
                            echo "Please type a file name."
                        fi
                        ;;
        getFile2)       defaultModifier="~"
                        defaultFile2=$File1$defaultModifier
                        echo -n "Filename 2 (default:" $defaultFile2 "): "
                        read File2
                        if ( test $File2 )
                        then
                            stateName="execDxdiff"
                            fusescript -state "execDxdiff"
                        else
                            File2=$defaultFile2
                            stateName="execDxdiff"
                            fusescript -state "execDxdiff"
                        fi
                        ;;
        execDxdiff)     echo "Executing command: dxdiff" $File1 $File2
                        dxdiff -geometry 900x440+50+400 $File1 $File2 &
                        bgProcess=$!
                        stateName="waiting"
                        fusescript -state "waiting"
                        ;;
        waiting)        if test $bgProcess -ne 0
                        then
                            ps | awk `{print $1}' | grep $bgProcess > /dev/null
                            bgRunning=$?
                            if test $bgRunning -eq 1
                            then
                                bgProcess=0
                                if test $triggered -eq 0
                                then
                                    stateName="exiting"
                                    fusescript -state "exiting"
                                else
                                    stateName="running"
                                    fusescript -state "running"
                                fi
                            fi
                        else
                            echo "Unable to start dxdiff in background"
                            if test $triggered -eq 0
                            then
                                stateName="exiting"
                                fusescript -state "exiting"
                            else
                                stateName="running"
                                fusescript -state "running"
                            fi
                        fi
                        ;;
        exiting)        ### if background process exists, stop it
                        if test $bgProcess -ne 0
                        then
                            kill $bgProcess
                        fi
                        ### if invoked by a trigger, clean up the files
                        ###    that were put in /tmp
                        if test $triggered -eq 0
                        then
                            if test -f $File1
                            then
                                rm $File1
                            fi
                            if test -f $File2
                            then
                                rm $File2
                            fi
                        fi
                        ### Send STOP event message and exit
                        fusescript -send ToolControlEvent "STOP"
                        stateName="done"
                        ;;
        *)              echo "Unknown state"
                        echo "   You should never see this message."
                        stateName="exiting"
                        fusescript -state "exiting"
                        ;;
    esac
done

echo "Exiting dxdiffScript..."
sleep 2
exit

The TIL file for the dxdiff example uses the script value for the language attribute. It is recommended that the path attribute specify starting a terminal window and a shell.

Example A-5: Example TIL File for Script Interface

/*
**  dxdiffProcessor.til
**
**  The DEC FUSE Tool Integration Language (TIL) file for the example program
**  that integrates dxdiff (the DECwindows visual differences program) into
**  a DEC FUSE environment
*/

/*  $Id: DOCU_008.HTM,v 1.1 1997/05/07 13:33:15 catano Exp $
*/
/*
 *
 * Copyright (c) 1993
 * Digital Equipment Corporation
 * All rights reserved.
 *
 * This software is furnished under a license and may be used and
 * copied  only  in accordance with the terms of such license and
 * with the  inclusion  of  the  above  copyright  notice.   This
 * software  or  any  other copies thereof may not be provided or
 * otherwise made available to any other person.  No title to and
 * ownership of the software is hereby transferred.
 *
 * The information in this software is subject to change  without
 * notice  and should not be construed as a commitment by Digital
 * Equipment Corporation.
 *
 * Digital assumes no responsibility for the use  or  reliability
 * of its software on equipment which is not supplied by Digital.
 *
*/

class DXDIFF_PROCESSOR = {
  Attributes {
    label = "dxdiff tool";
    accel = "Meta+F";
    path = "$(FUSE_TOP)/rundata/examples/EnCASE/dxdiff/dxdiffProcessor
     $(FUSE_TERM) -size 80x5 -geometry +200+266 -setup none -e
     /bin/sh $(FUSE_TOP)/rundata/examples/EnCASE/dxdiff/dxdiffScript";
    multiple = true;
    server = false;
    grouping = local;
    language = "script";
    active = true;
    dialog {
      normal = hide;
      auto = hide;
      recall = hide;
      request = hide;
    }
  }

  Messages {
        trigger void CompareRcsVersions(char *file, char *vers1, char *vers2);
#include "message_lib.msg"
  }

  States {

    start {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        MESSAGE_LIB_SEND
        }
    }
    running {
      receives {
        CompareRcsVersions,
        MESSAGE_LIB_RECV
        }
      sends {
        MESSAGE_LIB_SEND
        }
    }

    getFile2 {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        MESSAGE_LIB_SEND
        }
    }

    execDxdiff {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        MESSAGE_LIB_SEND
        }
    }

    waiting {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        MESSAGE_LIB_SEND
        }
    }

    exiting {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        MESSAGE_LIB_SEND
        }
    }
  }
}
class DXDIFF_TRIGGER = {

  Attributes {
    label = "dxdiff trigger";
    accel = "";
    path = "$(FUSE_TOP)/rundata/examples/EnCASE/dxdiff/dxdiffTrigger
     $(FUSE_TERM) -size 80x5 -geometry +200+132 -setup none -e /bin/sh";
    multiple = false;
    server = false;
    grouping = local;
    language = "script";
    active = true;
    dialog {
      normal = hide;
      auto = hide;
      recall = hide;
      request = hide;
    }
  }

  Messages {
        void CompareRcsVersions(char *file, char *vers1, char *vers2);
#include "message_lib.msg"
  }

  States {
    start {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        CompareRcsVersions,
        MESSAGE_LIB_SEND
        }
    }

    running {
      receives {
        MESSAGE_LIB_RECV
        }
      sends {
        CompareRcsVersions,
        MESSAGE_LIB_SEND
        }
    }
  }
}

Example A-6: Example Makefile for Script Interface

# # Makefile # # for the dxdiff integration example supplied with FUSE EnCASE. # # * $Id: DOCU_008.HTM,v 1.1 1997/05/07 13:33:15 catano Exp $ # * # * Copyright (c) 1991 # * Digital Equipment Corporation # * All rights reserved. # * # * This software is furnished under a license and may be used and # * copied only in accordance with the terms of such license and # * with the inclusion of the above copyright notice. This # * software or any other copies thereof may not be provided or # * otherwise made available to any other person. No title to and # * ownership of the software is hereby transferred. # * # * The information in this software is subject to change without # * notice and should not be construed as a commitment by Digital # * Equipment Corporation. # * # * Digital assumes no responsibility for the use or reliability # * of its software on equipment which is not supplied by Digital. # * CFLAGS= -O INCLUDES= -I$(FUSE_TOP)/include LD= /bin/ld # The libraries that integrated scripts need are in /usr/kits/fuse/lib LDFLAGS= -L$(FUSE_TOP)/lib # # Integrated scripts need the following 2 libraries: # # -lfuse : this is $FUSE_TOP/lib/libfuse.a # -lfusescript : this is $FUSE_TOP/lib/libfusescript.a # LIBRARIES= -lfuse -lfusescript all : dxdiffProcessor dxdiffTrigger dxdiffProcessor : FUSE_DXDIFF_PROCESSOR.o Makefile $(CC) -o $@ $(LDFLAGS) FUSE_DXDIFF_PROCESSOR.o $(LIBRARIES) FUSE_DXDIFF_PROCESSOR.o : FUSE_DXDIFF_PROCESSOR.c $(CC) -c -o FUSE_DXDIFF_PROCESSOR.o $(CFLAGS) $(INCLUDES) \e FUSE_DXDIFF_PROCESSOR.c FUSE_DXDIFF_PROCESSOR.c FUSE_DXDIFF_TRIGGER.c : dxdiffProcessor.til til -cDXDIFF_PROCESSOR -cDXDIFF_TRIGGER dxdiffProcessor.til dxdiffTrigger : FUSE_DXDIFF_TRIGGER.o Makefile $(CC) -o $@ $(LDFLAGS) FUSE_DXDIFF_TRIGGER.o $(LIBRARIES) FUSE_DXDIFF_TRIGGER.o : FUSE_DXDIFF_TRIGGER.c $(CC) -c -o FUSE_DXDIFF_TRIGGER.o $(CFLAGS) $(INCLUDES) \e FUSE_DXDIFF_TRIGGER.c clean : $(RM) -f FUSE*.* $(RM) -f *.o $(RM) -f dxdiffProcessor $(RM) -f dxdiffTrigger $(RM) -f fuseschema.msl $(RM) -f tools.rc


[Contents] [Prev. Chapter] [Prev. Section] [Index] [Help]