1 /*
2 * Copyright (C) 1998-2001 Mark Hessling <M.Hessling@qut.edu.au>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 * Mark Hessling M.Hessling@qut.edu.au http://www.lightlink.com/hessling/
19 */
20
21 static char RCSid[] = "$Id: loader.c,v 1.21 2005/07/03 07:58:51 mark Exp $";
22
23 #include "rxpack.h"
24
25 #ifndef R_OK
26 # define R_OK 4
27 #endif
28
29 #ifdef HAVE_PROTO
30 # if !defined(HAVE_GETOPT)
31 int getopt( int argc, char *argv[], char *optstring );
32 # endif
33 #else
34 # if !defined(HAVE_GETOPT)
35 int getopt( );
36 # endif
37 #endif
38
39 int gotOutput = 0;
40
41 /* These are required by the getopt() function */
42 extern char *optarg;
43 extern int optind;
44
45 extern PackageInitialiser *GETPACKAGEINITIALISER();
46 extern PackageTerminator *GETPACKAGETERMINATOR();
47 extern RexxSubcomHandler *GETPACKAGESUBCOMHANDLER();
48 extern RexxExitHandler *GETPACKAGEINITHANDLER();
49 extern RexxFunction *GETPACKAGEFUNCTIONS();
50 extern RxPackageConstantDef *GETPACKAGECONSTANTS();
51 extern void PACKAGEUSAGE();
52
53 #if defined(RUN_AS_GUI)
54 # include <windows.h>
55 # define STARTUPCONSOLE() StartupConsole()
56 # define CLOSEDOWNCONSOLE() ClosedownConsole()
StartupConsole(void)57 void StartupConsole( void )
58 {
59 if ( gotOutput == 0 )
60 {
61 AllocConsole();
62 freopen( "conin$", "r", stdin );
63 freopen( "conout$", "w", stdout );
64 freopen( "conout$", "w", stderr );
65 gotOutput = 1;
66 }
67 }
ClosedownConsole(void)68 void ClosedownConsole( void )
69 {
70 if ( gotOutput )
71 {
72 fprintf( stderr, "\n==> Press ENTER key to close this window. <==" );
73 getchar();
74 fclose(stdin);
75 fclose(stdout);
76 fclose(stderr);
77 gotOutput = 0;
78 }
79 }
80
RxExitHandlerForSayTraceRedirection(REH_ARG0_TYPE ExitNumber,REH_ARG1_TYPE Subfunction,REH_ARG2_TYPE ParmBlock)81 REH_RETURN_TYPE RxExitHandlerForSayTraceRedirection
82
83 #if defined(HAVE_PROTO)
84 ( REH_ARG0_TYPE ExitNumber, REH_ARG1_TYPE Subfunction, REH_ARG2_TYPE ParmBlock )
85 #else
86 ( ExitNumber, Subfunction, ParmBlock )
87 REH_ARG0_TYPE ExitNumber; /* code defining the exit function */
88 REH_ARG1_TYPE Subfunction; /* code defining the exit subfunction */
89 REH_ARG2_TYPE ParmBlock; /* function dependent control block */
90 #endif
91 {
92 long i = 0;
93 int rc = 0;
94
95 StartupConsole();
96
97 switch( Subfunction )
98 {
99 case RXSIOSAY:
100 {
101 RXSIOSAY_PARM *say_parm = (RXSIOSAY_PARM *)ParmBlock;
102 if ( say_parm->rxsio_string.strptr != NULL )
103 {
104 for( i = 0; i < (long)say_parm->rxsio_string.strlength; i++ )
105 {
106 fputc( ( char )say_parm->rxsio_string.strptr[i], stdout );
107 }
108 }
109 fputc( '\n', stdout );
110 rc = RXEXIT_HANDLED;
111 break;
112 }
113 case RXSIOTRC:
114 {
115 RXSIOTRC_PARM *trc_parm = (RXSIOTRC_PARM *)ParmBlock;
116 if ( trc_parm->rxsio_string.strptr != NULL )
117 {
118 for( i = 0; i < (long)trc_parm->rxsio_string.strlength; i++ )
119 {
120 fputc( ( char )trc_parm->rxsio_string.strptr[i], stderr );
121 }
122 }
123 fputc( '\n', stderr );
124 rc = RXEXIT_HANDLED;
125 break;
126 }
127 case RXSIOTRD:
128 {
129 RXSIOTRD_PARM *trd_parm = (RXSIOTRD_PARM *)ParmBlock;
130 int i = 0, ch = 0;
131 do
132 {
133 if ( i < 256 )
134 trd_parm->rxsiotrd_retc.strptr[i++] = ch = getc( stdin ) ;
135 } while( ch != '\012' && (ch != EOF ) ) ;
136 trd_parm->rxsiotrd_retc.strlength = i - 1;
137 rc = RXEXIT_HANDLED;
138 break;
139 }
140 case RXSIODTR:
141 {
142 RXSIODTR_PARM *dtr_parm = (RXSIODTR_PARM *)ParmBlock;
143 int i = 0, ch = 0;
144 do
145 {
146 if ( i < 256 )
147 dtr_parm->rxsiodtr_retc.strptr[i++] = ch = getc( stdin ) ;
148 } while( ch != '\012' && (ch != EOF ) ) ;
149 dtr_parm->rxsiodtr_retc.strlength = i - 1;
150 rc = RXEXIT_HANDLED;
151 break;
152 }
153 default:
154 rc = RXEXIT_NOT_HANDLED;
155 break;
156 }
157 return rc;
158 }
159 #else
160 # define STARTUPCONSOLE()
161 # define CLOSEDOWNCONSOLE()
162 #endif
163
164 /*-----------------------------------------------------------------------------
165 * Checks to see if supplied filename is readable.
166 *----------------------------------------------------------------------------*/
file_readable(char * filename)167 static int file_readable
168
169 #ifdef HAVE_PROTO
170 (char *filename)
171 #else
172 (filename)
173 char *filename;
174 #endif
175 {
176 if ((access(filename,R_OK)) == (-1))
177 return(0);
178 else
179 return(1);
180 }
181
182
183 /*-----------------------------------------------------------------------------
184 * Processing starts here for stand-alone rexxsql executable...
185 *----------------------------------------------------------------------------*/
main(int argc,char * argv[])186 int main
187
188 #if HAVE_PROTO
189 (int argc, char *argv[])
190 #else
191 (argc, argv)
192 int argc;
193 char *argv[];
194 #endif
195 {
196 int c=0;
197 char *ProgramName=NULL;
198 FILE *fp;
199 long i=0, ArgCount=0;
200 int interactive = FALSE;
201 int rc=0;
202 RXSTRING retstr;
203 CHAR retbuf[RETBUFLEN];
204 CHAR initexitname[100];
205 RXSTRING ArgList;
206 #if !defined(DYNAMIC_LIBRARY)
207 # if defined(USE_WINREXX) || defined(USE_QUERCUS)
208 RXSYSEXIT ExitList[3];
209 # elif defined(RUN_AS_GUI)
210 RXSYSEXIT ExitList[3];
211 # else
212 RXSYSEXIT ExitList[2];
213 # endif
214 #endif
215 RxPackageGlobalDataDef MyGlob, *RxPackageGlobalData;
216
217 memset( (char *)&MyGlob, 0, sizeof( RxPackageGlobalDataDef ) );
218
219 strcpy( MyGlob.RxTraceFileName, "stderr" );
220 strcpy( MyGlob.ConstantPrefix, "!" );
221 MyGlob.RxTraceFilePointer = stderr;
222 /*
223 * Get any program options.
224 */
225 while ((c = getopt(argc, argv, "Dudivh?f:")) != EOF)
226 {
227 switch (c)
228 {
229 case 'f':
230 strcpy( MyGlob.RxTraceFileName, optarg );
231 break;
232 case 'v':
233 MyGlob.RxRunFlags |= MODE_VERBOSE;
234 break;
235 case 'd':
236 MyGlob.RxRunFlags |= MODE_DEBUG;
237 break;
238 case 'D':
239 MyGlob.RxRunFlags |= MODE_INTERNAL;
240 break;
241 case 'i':
242 interactive = TRUE;
243 break;
244 case 'u':
245 DeregisterRxFunctions( &MyGlob, GETPACKAGEFUNCTIONS(), 1 );
246 return(0);
247 break;
248 case 'h':
249 default :
250 STARTUPCONSOLE();
251 PACKAGEUSAGE();
252 CLOSEDOWNCONSOLE();
253 exit(1);
254 }
255 }
256
257 /*
258 * Check if any more arguments are presented
259 */
260 if (optind >= argc)
261 {
262 if (interactive)
263 {
264 ProgramName = tmpnam(NULL);
265 if ((fp = fopen(ProgramName,"w")) == NULL)
266 {
267 STARTUPCONSOLE();
268 (void)fprintf(stderr, "Could not create temporary file for stdin\n");
269 CLOSEDOWNCONSOLE();
270 exit(REXX_FAIL);
271 }
272 for ( ; ; )
273 {
274 if ((i = getc(stdin)) == EOF)
275 break;
276 putc(i,fp);
277 }
278 (void)fclose(fp);
279 }
280 else
281 {
282 STARTUPCONSOLE();
283 PACKAGEUSAGE();
284 CLOSEDOWNCONSOLE();
285 exit(1);
286 }
287 }
288 else
289 {
290 /*
291 * Next argument is the name of the Rexx program...
292 */
293 ProgramName = argv[optind++];
294 /*
295 * ... and must be readable.
296 */
297
298 if (!file_readable(ProgramName))
299 {
300 STARTUPCONSOLE();
301 (void)fprintf(stderr, "Could not read file: %s\n",ProgramName);
302 CLOSEDOWNCONSOLE();
303 exit(REXX_FAIL);
304 }
305 }
306
307 /*
308 * Get number of arguments to the Rexx program
309 */
310 ArgCount = argc - optind;
311
312 /*
313 * Build an array of arguments if any.
314 */
315 if (ArgCount)
316 {
317 int len=0;
318
319 for ( i = optind; i < argc; i++ )
320 {
321 len += strlen( (char *)argv[i] );
322 }
323 if ( ( ArgList.strptr = (RXSTRING_STRPTR_TYPE)malloc( len + 1 + ArgCount) ) == (RXSTRING_STRPTR_TYPE)NULL )
324 {
325 STARTUPCONSOLE();
326 (void)fprintf( stderr, "%s: out of memory\n", argv[0] );
327 CLOSEDOWNCONSOLE();
328 exit( REXX_FAIL );
329 }
330 strcpy( ArgList.strptr, "" );
331 for ( i = optind; i < argc; i++ )
332 {
333 strcat( ArgList.strptr, (RXSTRING_STRPTR_TYPE)argv[optind++] );
334 if ( i != argc )
335 strcat( ArgList.strptr, (RXSTRING_STRPTR_TYPE)" " );
336 }
337 ArgList.strlength = ArgCount + len - 1;
338 }
339 else
340 {
341 ArgList.strptr = NULL;
342 ArgList.strlength = 0;
343 }
344
345 /*
346 * Initialise the package interface, but don't set the trace file
347 */
348 RxPackageGlobalData = InitRxPackage( &MyGlob, GETPACKAGEINITIALISER(), &rc );
349 if ( rc != 0 )
350 return( rc );
351 /*
352 * Register all external functions
353 */
354 if ( ( rc = RegisterRxFunctions( RxPackageGlobalData, GETPACKAGEFUNCTIONS(), RXPACKAGENAME ) ) != 0 )
355 return( rc );
356 /*
357 * Register a default subcommand handler to pass commands to the OS
358 */
359 if ( ( rc = RegisterRxSubcom( RxPackageGlobalData, GETPACKAGESUBCOMHANDLER() ) ) != 0 )
360 return( rc );
361 /*
362 * Register a RXINI handler to set the package constants
363 */
364 sprintf( initexitname, "%s%s", RXPACKAGENAME, "INIT" );
365 if ( ( rc = RegisterRxInit( RxPackageGlobalData, GETPACKAGEINITHANDLER(), initexitname ) ) != 0 )
366 return( rc );
367 FunctionPrologue( RxPackageGlobalData, GETPACKAGEINITIALISER(), RXPACKAGENAME, 0L, NULL );
368 /*
369 * Set up the system exit for the Say and Trace redirection and RxIni
370 */
371 #if !defined(DYNAMIC_LIBRARY)
372 # if defined(USE_WINREXX) || defined(USE_QUERCUS)
373 ExitList[0].sysexit_name = RXPACKAGENAME;
374 ExitList[0].sysexit_code = RXSIO;
375 ExitList[1].sysexit_name = initexitname;
376 ExitList[1].sysexit_code = RXINI;
377 ExitList[2].sysexit_code = RXENDLST;
378 #elif defined(RUN_AS_GUI)
379 /*
380 * Register the system exit
381 */
382 RexxRegisterExitExe( ( RREE_ARG0_TYPE )RXPACKAGENAME,
383 ( RREE_ARG1_TYPE )RxExitHandlerForSayTraceRedirection,
384 ( RREE_ARG2_TYPE )NULL);
385 ExitList[0].sysexit_name = RXPACKAGENAME;
386 ExitList[0].sysexit_code = RXSIO;
387 ExitList[1].sysexit_name = initexitname;
388 ExitList[1].sysexit_code = RXINI;
389 ExitList[2].sysexit_code = RXENDLST;
390 # else
391 ExitList[0].sysexit_name = initexitname;
392 ExitList[0].sysexit_code = RXINI;
393 ExitList[1].sysexit_code = RXENDLST;
394 # endif
395 #endif
396
397 MAKERXSTRING( retstr, retbuf, sizeof( retbuf ) );
398 /*
399 * Execute the Rexx script. Use RXCOMMAND mode so that the Rexx program
400 * expects the same parameter list if called directly via the Rexx
401 * interpreter.
402 */
403 RexxStart( ( RS_ARG0_TYPE )(ArgCount) ? 1 : 0,
404 ( RS_ARG1_TYPE )&ArgList,
405 ( RS_ARG2_TYPE )ProgramName,
406 ( RS_ARG3_TYPE )NULL,
407 ( RS_ARG4_TYPE )RXPACKAGENAME,
408 ( RS_ARG5_TYPE )RXCOMMAND,
409 #if !defined(DYNAMIC_LIBRARY)
410 ( RS_ARG6_TYPE )ExitList,
411 #elif defined(RUN_AS_GUI)
412 ( RS_ARG6_TYPE )ExitList,
413 #else
414 ( RS_ARG6_TYPE )NULL,
415 #endif
416 ( RS_ARG7_TYPE )&rc,
417 ( RS_ARG8_TYPE )&retstr);
418
419 if ( RxPackageGlobalData
420 && !RxPackageGlobalData->terminated )
421 {
422 rc = FunctionEpilogue( RxPackageGlobalData, RXPACKAGENAME, (ULONG)rc );
423 /*
424 * Terminate the package interface.
425 */
426 (void)TermRxPackage( &RxPackageGlobalData, GETPACKAGETERMINATOR(), GETPACKAGEFUNCTIONS(), RXPACKAGENAME, 0 );
427 RxPackageGlobalData = NULL;
428 }
429
430 if ( ArgList.strptr )
431 free(ArgList.strptr);
432 /*
433 * Return the exit value from the program. This is useful for UNIX/DOS etc.
434 * if the value is kept to 0-success, small positive numbers (say < 100)
435 * to indicate errors!
436 */
437 if ( interactive )
438 unlink( ProgramName );
439
440 CLOSEDOWNCONSOLE();
441 return rc;
442 }
443
444 #if defined(RUN_AS_GUI)
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)445 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
446 {
447 int rc;
448 rc = main( __argc, __argv );
449 return rc;
450 }
451 #endif
452