home *** CD-ROM | disk | FTP | other *** search
- /* RexxFuncHost.c */
-
-
- /* Copyright © 1989 by Donald T. Meyer
- * All Rights Reserved
- *
- * This source code may be compiled and used in any software
- * product.
- * No portion of this source code is to be
- * re-distributed or sold for profit without the written
- * permission of the author, Donald T. Meyer.
- *
- * Donald T. Meyer
- * Stormgate Software
- * 4 Rustic Creek Court
- * St. Peters, MO 63376
- *
- * BIX: donmeyer
- * GEnie: D.MEYER
- * PLINK: Stormgate
- */
-
-
-
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <workbench/startup.h>
-
- #include <proto/intuition.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- #include <string.h>
- #include <stdlib.h>
-
- #include "rexxfunchost.h"
-
-
-
- /*------------------------------------------------------------------*/
- /* External Function Declarations */
- /*------------------------------------------------------------------*/
-
- /* These are (better be!) in the user function module(s) */
-
- char *client_init( void );
-
- void client_cleanup( void );
-
-
-
- /*------------------------------------------------------------------*/
- /* External Variable Declarations */
- /*------------------------------------------------------------------*/
-
-
- /* These are in the user function module */
-
- extern char *hello_string;
- extern char *success_string;
- extern char *removal_string;
- extern char *redundant_string;
- extern char *noclone_string;
-
- extern struct RexxFunction func_table[];
-
- extern int hostpri;
- extern char *hostname;
-
- extern BPTR _Backstdout;
- extern char *console_def_string;
-
-
-
- /* Other misc. external variables. */
-
- extern struct WBStartup *WBenchMsg;
-
-
-
- /*------------------------------------------------------------------*/
- /* Local Function Declarations */
- /*------------------------------------------------------------------*/
-
- static void openlibrarys( void );
- static void closelibrarys( void );
-
- static void bailout( char *message, int rc );
-
- static void cleanup( void );
-
- static void init_port( void );
-
- static void eventloop( void );
-
- static int to_rexx( ULONG cmd, STRPTR arg0, STRPTR arg1, STRPTR arg2,
- STRPTR arg3 );
-
- static void handle_message( struct RexxMsg *rexxmsg );
-
- static void check_result( struct Rexxmsg *rexxmsg );
-
- static void dispatch( struct RexxMsg *rexxmsg );
-
- static void check_clone( int argc, char *argv[] );
-
- static BOOL remove_clone( void );
-
-
-
- /*------------------------------------------------------------------*/
- /* Variable Definitions */
- /*------------------------------------------------------------------*/
-
- struct RxsLib *RexxSysBase = NULL;
-
-
- static struct MsgPort *hostport = NULL;
-
- static BPTR message_console = NULL;
-
- static BOOL finished = FALSE;
-
- /* For detaching */
- long _BackGroundIO = 1;
-
-
-
- /*------------------------------------------------------------------*/
- /* Functions */
- /*------------------------------------------------------------------*/
-
-
- void main( int argc, char *argv[] )
- {
- char *errmsg;
-
-
- if( _Backstdout == NULL )
- {
- /* Probably child of workbench, open our own window */
- /* Open a window to print hello and copyright stuff to */
- message_console = Open( console_def_string, MODE_NEWFILE );
-
- /* After some thought, I decided to quit if we could not
- * post our hello banner, etc.
- * We could just as easily continue, but this _should_ never
- * fail, so probably moot.
- */
- if( message_console == NULL )
- bailout( NULL, 20 );
- }
- else
- {
- /* Send banner and error messages to the CLI that started us */
- message_console = _Backstdout;
- }
-
- openlibrarys();
-
- Write( message_console, hello_string, strlen(hello_string) );
-
- check_clone( argc, argv );
-
- init_port();
-
- /* Allow the client to do his initializations */
- if( ( errmsg = client_init() ) != NULL )
- {
- bailout( errmsg, 20 );
- }
-
- Write( message_console, success_string, strlen(success_string) );
-
- /* Done with window, close it */
- Delay( 200 );
- Close( message_console );
- message_console = NULL;
-
- eventloop();
-
- cleanup();
-
- exit( 0 );
- }
-
-
-
- static void eventloop( void )
- {
- struct RexxMsg *rexxmsg;
- ULONG flags;
-
-
- while( ! finished )
- {
- flags = Wait( ( 1L<<hostport->mp_SigBit ) | SIGBREAKF_CTRL_C );
-
- if( flags & SIGBREAKF_CTRL_C )
- {
- /* Somebody wants us to quit. Probably another us! */
- finished = TRUE;
-
- /* Remove ourselves from the arexx library list */
- to_rexx( (ULONG)RXREMLIB, hostname, NULL, NULL, NULL );
-
- /* Make port un-findable to all others just in case */
- RemPort( hostport );
- hostport->mp_Node.ln_Name = NULL;
- }
-
- while( rexxmsg = (struct RexxMsg *)GetMsg( hostport ) )
- {
- if( IsRexxMsg(rexxmsg) )
- {
- /* The message is from an ARexx program */
-
- /* Default to a "not found" code. */
- rexxmsg->rm_Result1 = RC_WARN;
- rexxmsg->rm_Result2 = ERR10_001;
-
- /* See if we have been told to close, and are just
- * flushing the message queue.
- */
- if( !finished )
- {
- /* Handle the message contents */
- handle_message( rexxmsg );
- }
- }
-
- ReplyMsg( (struct Message *)rexxmsg );
- }
- }
- }
-
-
-
- static void handle_message( struct RexxMsg *rexxmsg )
- {
- if( (rexxmsg->rm_Action & RXCODEMASK) != RXFUNC )
- {
- /* Something else (probably a command invocation if
- * our host port was set as the ARexx address).
- * We want to respond only to function invocations.
- */
- return;
- }
-
- dispatch( rexxmsg );
-
- check_result( rexxmsg );
- }
-
-
-
- static void dispatch( struct RexxMsg *rexxmsg )
- {
- int i, match = -1;
- char *cmd;
-
-
- cmd = ARG0(rexxmsg);
-
- for( i=0; func_table[i].fname != NULL; i++ )
- {
- if( func_table[i].caseflag == TRUE )
- {
- /* Case sensitive */
- if( strcmp( func_table[i].fname, cmd ) == 0 )
- {
- /* A match */
- match = i;
- break;
- }
- }
- else
- {
- /* Not case sensitive */
- if( stricmp( func_table[i].fname, cmd ) == 0 )
- {
- /* A match */
- match = i;
- break;
- }
- }
- }
-
- if( match == -1 )
- {
- /* No match found */
- return;
- }
-
- /* Found a match. Let's do the argument checking */
- if( ( func_table[match].argcount != -1 ) &&
- ( ( rexxmsg->rm_Action & RXARGMASK ) !=
- func_table[match].argcount ) )
- {
- /* Wrong number of args */
- rexxmsg->rm_Result1 = RC_ERROR;
- rexxmsg->rm_Result2 = ERR10_017;
- return;
- }
-
- /* Call the function. */
- (*(func_table[match].func))(rexxmsg);
- }
-
-
-
- static void check_result( struct RexxMsg *rexxmsg )
- {
- /* Make sure that we don't return an argstring
- * if one was not requested
- */
- if( rexxmsg->rm_Action & RXFF_RESULT )
- {
- /* Result string wanted */
- return;
- }
-
-
- /* A result string was not requested. Let's see if there is one */
-
- if( (rexxmsg->rm_Result1==0) && (rexxmsg->rm_Result2!=0) )
- {
- /* There is one, so we need to delete it. */
- DeleteArgstring( (struct RexxArg *)(rexxmsg->rm_Result2) );
- rexxmsg->rm_Result2 = 0;
- }
- }
-
-
-
- /* Open a public port and add it to the ARexx Library List.
- */
-
- static void init_port( void )
- {
- /* Setup the public host port */
- if( ( hostport = CreatePort( hostname, 0L ) ) == NULL )
- {
- bailout( "Unable to create message port", 20 );
- }
-
- /* Add ourselves to the arexx library list */
- if( to_rexx( (ULONG)RXADDFH, hostname, (STRPTR)hostpri, NULL, NULL ) )
- {
- /* Could not add our port to the library list */
- bailout( "Unable to add self to ARexx library list", 20 );
- }
- }
-
-
- /* This function does some fairly convoluted things involving
- * terminating another previously running invocation of ourselves.
- * Depending on wether we are launched from CLI or WorkBench and
- * command line options (only if from the CLI of course).
- * The logic is:
- *
- * IF from WorkBench
- * IF already invoked
- * remove existing invocation
- * exit
- *
- * IF from CLI
- * IF -q option
- * IF already invoked
- * remove existing invocation
- * exit
- * ELSE
- * tell user there is no existing invocation
- * exit
- * ELSE
- * IF already invoked
- * tell user that we cannot install again
- * exit
- *
- */
-
- static void check_clone( int argc, char *argv[] )
- {
- if( WBenchMsg )
- {
- /* We are running from workbench, see if we want to
- * kill off the existing invocation.
- */
- if( remove_clone() )
- {
- /* There was and we did */
- bailout( removal_string, 0 );
- }
- /* Else, there was no clone, continue execution. */
- }
- else
- {
- /* From the CLI. If the argument "-q" is given, we try to kill
- * the existing invocation. Otherwise we just refuse
- * to start another invocation.
- */
- if( ( argc > 1 ) && ( stricmp(argv[1],"-q") == 0 ) )
- {
- /* User wants us to remove ourselves */
- if( remove_clone() )
- {
- /* There was and we did */
- bailout( removal_string, 0 );
- }
- else
- {
- /* There was no previous invocation */
- bailout( noclone_string, 5 );
- }
- }
- else
- {
- /* The user is trying to invoke us. */
- if( FindPort( hostname ) )
- {
- /* But we already exist */
- bailout( redundant_string, 5 );
- }
- }
- }
- }
-
-
-
- /* If thereis already another instance of ourselves running, kill it
- * and return TRUE, otherwise return FALSE.
- */
-
- static BOOL remove_clone( void )
- {
- struct MsgPort *otherport;
-
-
- if( ( otherport = FindPort( hostname ) ) != NULL )
- {
- /* Yes, we are */
- Signal( otherport->mp_SigTask, SIGBREAKF_CTRL_C );
- return( TRUE );
- }
-
- return( FALSE );
- }
-
-
-
- static void openlibrarys( void )
- {
- /* ARexx library */
- if( ! ( RexxSysBase = (struct RxsLib *)OpenLibrary( RXSNAME, 0L) ) )
- {
- bailout( "Unable to open the ARexx Library", 20 );
- }
- }
-
-
-
- static void closelibrarys( void )
- {
- if( RexxSysBase )
- CloseLibrary( (struct Library *)RexxSysBase );
- }
-
-
-
- static void cleanup( void )
- {
- client_cleanup();
-
- /* Remove ourselves from the arexx library list */
- to_rexx( (ULONG)RXREMLIB, hostname, NULL, NULL, NULL );
-
- if( hostport )
- DeletePort( hostport );
-
- closelibrarys();
-
- if( message_console )
- Close( message_console );
- }
-
-
-
-
- static void bailout( char *message, int rc )
- {
- if( message_console )
- {
- Write( message_console, message, strlen(message) );
- Delay( 200 );
- }
-
- cleanup();
-
- exit( rc );
- }
-
-
-
- static int to_rexx( ULONG cmd, STRPTR arg0, STRPTR arg1, STRPTR arg2,
- STRPTR arg3 )
- {
- struct MsgPort *rmast;
- struct RexxMsg *rexxmsg;
-
-
- /* Allocate a packet to send to rexxmaster */
- rexxmsg = CreateRexxMsg( NULL, NULL, NULL );
- if( rexxmsg == NULL )
- {
- return( 1 );
- }
-
- rexxmsg->rm_Action = cmd | (1L<<RXFB_NONRET);
-
- rexxmsg->rm_Args[0] = arg0;
- rexxmsg->rm_Args[1] = arg1;
- rexxmsg->rm_Args[2] = arg2;
- rexxmsg->rm_Args[3] = arg3;
-
- Forbid();
- if( rmast = FindPort( "REXX" ) )
- {
- PutMsg( rmast, (struct Message *)rexxmsg );
- }
- Permit();
-
- if( rmast == NULL )
- {
- /* we could not find the REXX port, this failed! */
- DeleteRexxMsg( rexxmsg );
- return( 2 );
- }
-
- return( 0 );
- }
-
-
-
- /* This can be called to handle the details of placing a result
- * string into the rexx message packet as the result Argstring.
- * This will deal with inability to allocate the Argstring.
- * If the string pointer is NULL, a general failure code will
- * be set.
- */
-
- void SetResultString( struct RexxMsg *rexxmsg, char *string )
- {
- if( string )
- {
- rexxmsg->rm_Result1 = RC_OK;
- rexxmsg->rm_Result2 =
- (ULONG)CreateArgstring( string, strlen(string) );
-
- if( rexxmsg->rm_Result2 == NULL )
- {
- /* Unable to create the argstring */
- rexxmsg->rm_Result1 = RC_ERROR;
- rexxmsg->rm_Result2 = ERR10_012;
- }
- }
- else
- {
- /* Result string is null, set general failure code */
- rexxmsg->rm_Result1 = RC_ERROR;
- rexxmsg->rm_Result2 = ERR10_012;
- }
- }
-
-