home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
530b.lha
/
AMenu_v1.3
/
Run.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-03
|
9KB
|
268 lines
/*********************************************************************\
** ________________________________ **
** A n t h o n y |________ __ __ ________| **
** | |o_| |o_| | **
** T h y s s e n __| __ __ |__ **
** __| __| | | |__ |__ **
** `` Dragon Computing ! '' __| __| | | |__ |__ **
** |_____| |__| |_____| **
** **
\*********************************************************************/
#include "AMenu.h"
#include "AllocStr.h"
#include <libraries/DosExtens.h> /* for Process definition */
#include <Workbench/Startup.h> /* for WBStartup definition */
#include <Workbench/WorkBench.h> /* for DiskObject definition */
#include <Proto/Icon.h>
#include <string.h>
extern struct Process *MyProc; /* This Process */
extern BPTR WorkDirLock; /* The current directory */
extern void Warn(char *); /* routine to notify user of error */
/*-----------------------------------------------------*/
static void
RunCLI( EItem )
struct ExtMenuItem *EItem;
/* execute a CLI command using the appropiate console
** for command (either a default or commands own).
*/
{
struct ProcessControlBlock *PCB=NULL; /* structure for Arp's ASynchRun */
BPTR NewDirLock=NULL; /* Directory Lock for CD */
long CLI=0; /* result code - CLI number used */
char buf[256], *ConWin, *Error;
DB( FPrintf(DBWindow, "CLIRun -> `%s'\n", EItem->Cmd); )
/* is new Directory Update the directory */
if( EItem->Directory ) {
if( !( NewDirLock = Lock(EItem->Directory, ACCESS_READ) ) ) {
SPrintf(buf, "Unable to Find Directory `%s' ", EItem->Directory);
Warn(buf); return;
}
CurrentDir(NewDirLock);
}
PCB = (struct ProcessControlBlock *)
AllocMem( sizeof(struct ProcessControlBlock), MEMF_CLEAR|MEMF_PUBLIC);
if( !PCB )
CLI = PR_NOMEM; /* failed to allocate PCB struct */
else {
/* allocate appropiate stack and prioity */
PCB->pcb_StackSize = EItem->Stack; /* Stack */
PCB->pcb_Pri = EItem->Pri; /* Pri */
ConWin = ( EItem->Console ? EItem->Console : M->Console );
switch( EItem->Mode ) {
case 'C': /* CLI mode - Open a Console */
PCB->pcb_Control = PRF_STDIO;
PCB->pcb_Console.pcb_ConName = (BYTE *) ConWin;
break;
case 'R': /* RunBack - No File Handles */
PCB->pcb_Control = PRF_SAVEIO;
break;
case 'S': /* Script - New Shell */
PCB->pcb_Control = INTERACTIVE_SHELL;
}
DB( FPrintf(DBWindow, "-- ASynchRun()\n"); )
CLI = ( EItem->Mode == 'S' )
? ASyncRun( ConWin, EItem->Cmd, PCB) /* interactive shell */
: ASyncRun( EItem->Cmd, EItem->Args, PCB); /* run command */
}
/* Handle Errors */
if( CLI<0 ) { /* negitive result -- Report Appropiate Error */
switch( CLI ) {
case PR_NOSTDIO: Error = "%s: Unable to open Console"; break;
case PR_NOFILE: Error = "%s: Unknowen Command `%s'"; break;
case PR_NOMEM: Error = "%s: Not Enough Memory"; break;
case PR_NOSLOT: Error = "%s: Task Table Full"; break;
case PR_NOINPUT:
case PR_NOOUTPUT: Error = "%s: IO Error on Console"; break;
case PR_SCRIPT: Error = "%s: Script run using wrong mode"; break;
default: Error = "%s: ASynchRun Failed on `%s' (%ld)";
}
SPrintf(buf, Error, VERSION, EItem->Cmd, CLI);
Warn(buf);
}
if( PCB )
FreeMem( PCB, sizeof(struct ProcessControlBlock) );
if( EItem->Directory ) /* Return to the Working Directory */
UnLock( CurrentDir( WorkDirLock ) );
DB( FPrintf(DBWindow, "---- Done ----\n"); )
}
/*--------------------------------------------------*/
/* procedures to support running WorkBench programs */
extern WBProcesses; /* WB processes currently running */
extern struct MsgPort *WBReplyPort; /* Port for Process to reply to */
void
WBFree( StartMsg )
struct WBStartup *StartMsg;
/* Free up space used by a workbench startup message. Called whenever
* a workbench program replies to the startup message, and whenever
* `WBRun()' gets an error
*/
{
register int i;
if( StartMsg ) {
if( WBProcesses ) /* decrement number of processes */
WBProcesses--;
if( StartMsg->sm_ArgList ) {
for (i=0; i<StartMsg->sm_NumArgs; i++) {
if( StartMsg->sm_ArgList[i].wa_Lock )
UnLock(StartMsg->sm_ArgList[i].wa_Lock);
if( StartMsg->sm_ArgList[i].wa_Name )
FreeStr(StartMsg->sm_ArgList[i].wa_Name);
}
FreeMem( StartMsg->sm_ArgList,
sizeof(struct WBArg) *StartMsg->sm_NumArgs );
}
if( StartMsg->sm_Segment )
UnLoadSeg(StartMsg->sm_Segment);
if( StartMsg->sm_ToolWindow )
FreeStr(StartMsg->sm_ToolWindow );
FreeMem( StartMsg , sizeof(struct WBStartup) );
}
}
static void
RunWB( EItem )
struct ExtMenuItem *EItem;
/* load and run a workbench program
* This routine is errored in the following ways
* 1/ No ToolTypes are handled
* 2/ The TOOL for a PROJECT is expected to have an icon (it may not!).
* 3/ Current Directory is that of the TOOL not the PROJECT or
* 4/ User can't select the Current Directory to use (should he?).
* -- Anthony Thyssen
*/
{
BPTR DirLock = NULL, OldLock = NULL, IconLock;
struct WBStartup *StartMsg = NULL;
struct DiskObject *DiskObject = NULL;
char *Name, buf[128];
BOOL Error = TRUE; /* assume the worst */
int I;
/* Lock Projects Directory */
Name = BaseName(EItem->Cmd);
strcpy(buf, EItem->Cmd);
strcat(buf, ".info"); /* this will be present the project may not! */
if( !(IconLock = Lock(buf, ACCESS_READ) ) ) {
SPrintf(buf, "Can't locate `%s.info'", Name);
goto finish;
}
DirLock = ParentDir(IconLock);
UnLock(IconLock);
if( !DirLock ) {
SPrintf(buf, "Directory invalid for `%s'", EItem->Cmd);
goto finish;
}
/* Load Icon */
OldLock = CurrentDir( DirLock );
if( !(DiskObject = GetDiskObject(Name)) ) {
SPrintf(buf, "Can't locate `%s.info'", Name);
goto finish;
}
switch( DiskObject->do_Type ) {
case WBTOOL: I=1; break; /* just the tool */
case WBPROJECT: I=2; break; /* tool & project */
default:
SPrintf(buf, "`%s.info' is not a TOOL or PROJECT!", Name);
goto finish;
}
/* allocate the startup message */
if( !(StartMsg = (struct WBStartup *)
AllocMem( sizeof(struct WBStartup), MEMF_PUBLIC|MEMF_CLEAR))) {
SPrintf(buf, "%s: Not Enough Memory", VERSION);
goto finish;
}
StartMsg->sm_NumArgs = I;
if( !(StartMsg->sm_ArgList = (struct WBArg *)
AllocMem( sizeof(struct WBArg)*I, MEMF_PUBLIC|MEMF_CLEAR)) ) {
SPrintf(buf, "%s: Not Enough Memory", VERSION);
goto finish;
}
I--; /* Fill in the Last WBArg the TOOL/Project we referenced */
StartMsg->sm_ArgList[I].wa_Lock = DirLock;
StartMsg->sm_ArgList[I].wa_Name = AllocStr(Name);
if( I ) { /* if WBPROJECT - Fill out the Tool */
StartMsg->sm_ArgList->wa_Lock = DupLock(DirLock); /* same as project */
StartMsg->sm_ArgList->wa_Name = AllocStr(DiskObject->do_DefaultTool);
Name = StartMsg->sm_ArgList->wa_Name; /* Set the new name */
}
/* initialize rest of startup message */
StartMsg->sm_Message.mn_ReplyPort = WBReplyPort;
StartMsg->sm_Message.mn_Length = sizeof(struct WBStartup);
StartMsg->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
StartMsg->sm_ToolWindow = AllocStr(DiskObject->do_ToolWindow);
/* Insure a decent stack size, some progs have this set to zero */
if( DiskObject->do_StackSize < EItem->Stack )
DiskObject->do_StackSize = EItem->Stack;
/* load in the program */
if( !(StartMsg->sm_Segment = LoadPrg(Name)) ) {
SPrintf(buf, "Unable to Load `%s'", Name);
goto finish;
}
/* create process */
if( !(StartMsg->sm_Process = CreateProc( Name, (LONG)EItem->Pri,
StartMsg->sm_Segment, DiskObject->do_StackSize)) ) {
SPrintf(buf, "Can't execute `%s'", Name);
goto finish;
}
/* everything's ok -- start 'er up */
PutMsg( StartMsg->sm_Process , (struct Message *)StartMsg );
Error = FALSE;
WBProcesses++; /* keep track of unreplied startup messages */
finish:
if( DiskObject ) FreeDiskObject( DiskObject );
if( OldLock ) CurrentDir( OldLock );
if( Error ) {
if( StartMsg ) WBFree( StartMsg );
Warn(buf);
}
}
/*-------------------------------------------------*/
void
RunItem( EItem )
struct ExtMenuItem *EItem;
{
switch( EItem->Mode ) {
case 'R':
case 'C':
case 'S': RunCLI( EItem ); break;
case 'W': RunWB( EItem ); break;
}
}