home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
230.lha
/
ArexxFunctionHost
/
rexxfunchost.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-03
|
11KB
|
574 lines
/* 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;
}
}