Files
PDCurses/common/loader.c
2003-01-01 05:08:37 +00:00

278 lines
7.6 KiB
C

/*
* Copyright (C) 1998-2001 Mark Hessling <M.Hessling@qut.edu.au>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Mark Hessling M.Hessling@qut.edu.au http://www.lightlink.com/hessling/
*/
static char RCSid[] = "$Id: loader.c,v 1.11 2003/01/01 05:08:35 mark Exp $";
#include "rxpack.h"
#ifndef R_OK
# define R_OK 4
#endif
#ifdef HAVE_PROTO
# if !defined(HAVE_GETOPT)
int getopt( int argc, char *argv[], char *optstring );
# endif
#else
# if !defined(HAVE_GETOPT)
int getopt( );
# endif
#endif
/* These are required by the getopt() function */
extern char *optarg;
extern int optind;
extern PackageInitialiser *GETPACKAGEINITIALISER();
extern PackageTerminator *GETPACKAGETERMINATOR();
extern RexxSubcomHandler *GETPACKAGESUBCOMHANDLER();
extern RexxFunction *GETPACKAGEFUNCTIONS();
extern void PACKAGEUSAGE();
/*-----------------------------------------------------------------------------
* Checks to see if supplied filename is readable.
*----------------------------------------------------------------------------*/
static int file_readable
#ifdef HAVE_PROTO
(char *filename)
#else
(filename)
char *filename;
#endif
{
if ((access(filename,R_OK)) == (-1))
return(0);
else
return(1);
}
/*-----------------------------------------------------------------------------
* Processing starts here for stand-alone rexxsql executable...
*----------------------------------------------------------------------------*/
int main
#if HAVE_PROTO
(int argc, char *argv[])
#else
(argc, argv)
int argc;
char *argv[];
#endif
{
int c=0;
char *ProgramName=NULL;
FILE *fp;
long i=0, ArgCount=0;
int interactive = FALSE;
int rc=0;
RXSTRING retstr;
CHAR retbuf[RETBUFLEN];
RXSTRING ArgList;
#if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
RXSYSEXIT ExitList[2];
#endif
RxPackageGlobalDataDef MyGlob, *RxPackageGlobalData;
memset( (char *)&MyGlob, 0, sizeof( RxPackageGlobalDataDef ) );
strcpy( MyGlob.RxTraceFileName, "stderr" );
MyGlob.RxTraceFilePointer = stderr;
/*
* Get any program options.
*/
while ((c = getopt(argc, argv, "Dudivh?f:")) != EOF)
{
switch (c)
{
case 'f':
strcpy( MyGlob.RxTraceFileName, optarg );
break;
case 'v':
MyGlob.RxRunFlags |= MODE_VERBOSE;
break;
case 'd':
MyGlob.RxRunFlags |= MODE_DEBUG;
break;
case 'D':
MyGlob.RxRunFlags |= MODE_INTERNAL;
break;
case 'i':
interactive = TRUE;
break;
case 'u':
DeregisterRxFunctions( &MyGlob, GETPACKAGEFUNCTIONS(), 1 );
return(0);
break;
case 'h':
default : PACKAGEUSAGE();
}
}
/*
* Check if any more arguments are presented
*/
if (optind >= argc)
{
if (interactive)
{
ProgramName = tmpnam(NULL);
if ((fp = fopen(ProgramName,"w")) == NULL)
{
(void)fprintf(stderr, "Could not create temporary file for stdin\n");
exit(REXX_FAIL);
}
for ( ; ; )
{
if ((i = getc(stdin)) == EOF)
break;
putc(i,fp);
}
(void)fclose(fp);
}
else
PACKAGEUSAGE();
}
else
{
/*
* Next argument is the name of the Rexx program...
*/
ProgramName = argv[optind++];
/*
* ... and must be readable.
*/
if (!file_readable(ProgramName))
{
(void)fprintf(stderr, "Could not read file: %s\n",ProgramName);
exit(REXX_FAIL);
}
}
/*
* Get number of arguments to the Rexx program
*/
ArgCount = argc - optind;
/*
* Build an array of arguments if any.
*/
if (ArgCount)
{
int len=0;
for ( i = optind; i < argc; i++ )
{
len += strlen( (char *)argv[i] );
}
if ( ( ArgList.strptr = (RXSTRING_STRPTR_TYPE)malloc( len + 1 + ArgCount) ) == (RXSTRING_STRPTR_TYPE)NULL )
{
(void)fprintf( stderr, "%s: out of memory\n", argv[0] );
exit( REXX_FAIL );
}
strcpy( ArgList.strptr, "" );
for ( i = optind; i < argc; i++ )
{
strcat( ArgList.strptr, (RXSTRING_STRPTR_TYPE)argv[optind++] );
if ( i != argc )
strcat( ArgList.strptr, (RXSTRING_STRPTR_TYPE)" " );
}
ArgList.strlength = ArgCount + len - 1;
}
else
{
ArgList.strptr = NULL;
ArgList.strlength = 0;
}
/*
* Initialise the package interface, but don't set the trace file
*/
RxPackageGlobalData = InitRxPackage( &MyGlob, GETPACKAGEINITIALISER(), &rc );
if ( rc != 0 )
return( rc );
/*
* Register all external functions
*/
if ( ( rc = RegisterRxFunctions( RxPackageGlobalData, GETPACKAGEFUNCTIONS(), RXPACKAGENAME ) ) != 0 )
return( rc );
/*
* Register a default subcommand handler to pass commands to the OS
*/
if ( ( rc = RegisterRxSubcom( RxPackageGlobalData, GETPACKAGESUBCOMHANDLER() ) ) != 0 )
return( rc );
FunctionPrologue( RxPackageGlobalData, GETPACKAGEINITIALISER(), RXPACKAGENAME, 0L, NULL );
/*
* Set up the system exit for the Say and Trace redirection
*/
#if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
ExitList[0].sysexit_name = RXPACKAGENAME;
ExitList[0].sysexit_code = RXSIO;
ExitList[1].sysexit_code = RXENDLST;
#endif
MAKERXSTRING( retstr, retbuf, sizeof( retbuf ) );
/*
* Execute the Rexx script. Use RXCOMMAND mode so that the Rexx program
* expects the same parameter list if called directly via the Rexx
* interpreter.
*/
assert(retstr.strptr);
assert(ProgramName);
RexxStart( ( RS_ARG0_TYPE )(ArgCount) ? 1 : 0,
( RS_ARG1_TYPE )&ArgList,
( RS_ARG2_TYPE )ProgramName,
( RS_ARG3_TYPE )NULL,
( RS_ARG4_TYPE )RXPACKAGENAME,
( RS_ARG5_TYPE )RXCOMMAND,
#if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
( RS_ARG6_TYPE )ExitList,
#else
( RS_ARG6_TYPE )NULL,
#endif
( RS_ARG7_TYPE )&rc,
( RS_ARG8_TYPE )&retstr);
if ( RxPackageGlobalData
&& !RxPackageGlobalData->terminated )
{
rc = FunctionEpilogue( RxPackageGlobalData, RXPACKAGENAME, (ULONG)rc );
/*
* Terminate the package interface.
*/
(void)TermRxPackage( &RxPackageGlobalData, GETPACKAGETERMINATOR(), GETPACKAGEFUNCTIONS(), RXPACKAGENAME, 0 );
RxPackageGlobalData = NULL;
}
if ( ArgList.strptr )
free(ArgList.strptr);
/*
* Return the exit value from the program. This is useful for UNIX/DOS etc.
* if the value is kept to 0-success, small positive numbers (say < 100)
* to indicate errors!
*/
if ( interactive )
unlink( ProgramName );
return rc;
}