/* * Run.c - Copyright © 1990 by S.R. & P.C. * * Created: 16 Jun 1990 * Modified: 07 Jul 1990 * * Make>> make */ /* #define DO_ARP_COPIES #include #include #include #include #include #include */ #include #include #include "ParM.h" /* Error messages */ static const char *ErrNoMem = "Out of memory!"; static const char *NoCmd = "Can't execute command!"; static const char *NoInfo = "Can't open info file!"; /***** external functions *****/ extern char *copystr( char * ); extern void Warn( const char * ); /***** global functions *****/ void DoExtMenu( USHORT ); void WBFree( struct WBStartup * ); /***** global variables *****/ extern struct Menu Menu1; extern struct Process *MyProcess; extern struct MsgPort *WBReplyPort; extern short WBCnt; /* execute a RB command */ static BOOL RunBack(char *cmd, char *args) { BPTR NilFh; char buf[256]; BOOL ret; SPrintf(buf,"Run >NIL: NIL: pcb_StackSize = emi->emi_Stack; pcb->pcb_Pri = emi->emi_Pri; pcb->pcb_Console.pcb_ConName = emi->emi_Window; pcb->pcb_Control = PRF_STDIO; CLI = ASyncRun(emi->emi_Cmd, emi->emi_Args, pcb); FreeMem(pcb, sizeof(struct ProcessControlBlock)); if (CLI<=0) { switch( CLI ) { case PR_NOFILE : Warn("Command not found"); break; case PR_NOSTDIO : Warn("Can't open window"); break; default : Warn(NoCmd); } } } else Warn(ErrNoMem); } /* procedures to support running WorkBench programs */ /* 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 */ void WBFree( struct WBStartup *WBStartup ) { register BPTR lock; register int i; register char *cp; if( WBStartup ) { if( WBStartup->sm_ArgList ) { for (i=0; ism_NumArgs; i++) { if( (lock=WBStartup->sm_ArgList[i].wa_Lock) ) UnLock(lock); if( (cp=WBStartup->sm_ArgList[i].wa_Name) ) FreeMem(cp, strlen(cp)+1); } FreeMem(WBStartup->sm_ArgList,sizeof(struct WBArg)*WBStartup->sm_NumArgs); } if( WBStartup->sm_Segment ) UnLoadSeg(WBStartup->sm_Segment); if( cp=WBStartup->sm_ToolWindow ) FreeMem(cp, strlen(cp)+1); FreeMem( WBStartup , sizeof(struct WBStartup) ); } } /* take the path passed, and split it into a lock and name, suitable for putting into a WBArg structure */ static void SplitPath( char *path, BPTR *dir_lock, char **name) { register BPTR lock; *name = BaseName(path); lock = Lock(path, ACCESS_READ); if( lock ) { *dir_lock = (BPTR)ParentDir((struct FileLock *)lock); UnLock(lock); } else *dir_lock = DupLock(MyProcess->pr_CurrentDir); } /* load and run a workbench program */ static void WBRun( char *cmd ) { BPTR lock = NULL, OldLock = NULL; struct WBStartup *WBStartup = NULL; struct DiskObject *disk_object = NULL; char *name, buf[128]; BOOL error = TRUE; /* assume the worst */ /* allocate the startup message */ if( !(WBStartup = (struct WBStartup *)AllocMem(sizeof(struct WBStartup),MEMF_PUBLIC|MEMF_CLEAR)) ) { Warn(ErrNoMem); return; /* don't go to finish:, nothing allocated yet */ } /* find the directory and name of the program to run */ SplitPath(cmd, &lock, &name); if( !lock ) { Warn(NoCmd); goto finish; } /* try to load in the .info file */ OldLock = (BPTR)CurrentDir((struct FileLock *)lock); if( !(disk_object = GetDiskObject(name)) ) { Warn(NoInfo); goto finish; } /* allocate the WBArgs - if we are a tool, we allocate one */ /* of these, else two (one for tool, one for project) */ if( disk_object->do_Type == WBTOOL ) { if( !(WBStartup->sm_ArgList = (struct WBArg *)AllocMem(sizeof(struct WBArg), MEMF_PUBLIC|MEMF_CLEAR)) ) { Warn(ErrNoMem); goto finish; } WBStartup->sm_NumArgs = 1; } else if( disk_object->do_Type == WBPROJECT ) { if( !(WBStartup->sm_ArgList = (struct WBArg *)AllocMem(sizeof(struct WBArg)*2, MEMF_PUBLIC|MEMF_CLEAR)) ) { Warn(ErrNoMem); goto finish; } WBStartup->sm_NumArgs = 2; /* fill in arg #2 with the info we already have */ WBStartup->sm_ArgList[1].wa_Lock = (BPTR)lock; WBStartup->sm_ArgList[1].wa_Name = copystr(name); /* now find the tool */ strcpy( buf , disk_object->do_DefaultTool ); SplitPath( buf , &lock , &name ); FreeDiskObject( disk_object ); CurrentDir( (struct FileLock *)lock ); if( !(disk_object = GetDiskObject(name)) ) { Warn(NoInfo); goto finish; } /* we have to have a tool at this point - or else */ if( disk_object->do_Type != WBTOOL ) { Warn("Not a tool or project!"); goto finish; } } /* fill in arguments */ WBStartup->sm_ArgList[0].wa_Lock = (BPTR)lock; WBStartup->sm_ArgList[0].wa_Name = copystr(name); /* initialize rest of startup message */ WBStartup->sm_Message.mn_ReplyPort = WBReplyPort; WBStartup->sm_Message.mn_Length = sizeof(struct WBStartup); WBStartup->sm_Message.mn_Node.ln_Type = NT_MESSAGE; WBStartup->sm_ToolWindow = copystr(disk_object->do_ToolWindow); /* get a decent stack size, there are a few progs that set this to zero */ if( disk_object->do_StackSize < 4000 ) disk_object->do_StackSize = 4000; /* load in the program */ if( !(WBStartup->sm_Segment = (BPTR)LoadPrg(name)) ) { Warn(NoCmd); goto finish; } /* create process */ if( !(WBStartup->sm_Process = (struct MsgPort *)CreateProc(name, 0, WBStartup->sm_Segment, disk_object->do_StackSize)) ) { Warn(NoCmd); goto finish; } /* everything's ok -- start 'er up */ PutMsg( WBStartup->sm_Process , (struct Message *)WBStartup ); error = FALSE; WBCnt++; /* keep track of unreplied startup messages */ finish: if( disk_object ) FreeDiskObject( disk_object ); CurrentDir( (struct FileLock *)OldLock ); if( error ) WBFree( WBStartup ); } void DoExtMenu( USHORT MenuNum ) { struct Extended_MenuItem *Item; Item = (struct Extended_MenuItem *)ItemAddress( &Menu1 , MenuNum ); switch( Item->emi_Mode ) { case 'r' : if( !RunBack(Item->emi_Cmd,Item->emi_Args) ) Warn(NoCmd); break; case 'c' : CLIRun(Item); break; case 'w' : WBRun( Item->emi_Cmd ); break; } }