This appendix provides listings for the following source files
Section A.1
lists
the entire
.h
and
.c
source
files for the example used in
Chapter 4.
Section A.2
lists the source file,
TIL file, and makefile for an example of using the script interface
to integrate
dxdiff
into FUSE.
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/EnCASE
directory for source files specific to your platform.
Note
The
dxdiff
example does not work on Sun systems because there is no equivalentdxdiff
utility on Sun.
Example A-1
is the
complete header file for the
minigrep
example.
/* ** 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.
/* 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 */
/* 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
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.
#!/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.
/* ** 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 } } } }
# # 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