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 >
C/C++ Source or Header  |  1991-07-03  |  9KB  |  268 lines

  1. /*********************************************************************\
  2. **                               ________________________________    **
  3. **    A n t h o n y             |________    __    __    ________|   **
  4. **                                       |  |o_|  |o_|  |            **
  5. **            T h y s s e n            __|   __    __   |__          **
  6. **                                  __|   __|  |  |  |__   |__       **
  7. **   `` Dragon Computing ! ''    __|   __|     |  |     |__   |__    **
  8. **                              |_____|        |__|        |_____|   **
  9. **                                                                   **
  10. \*********************************************************************/
  11.  
  12. #include "AMenu.h"
  13. #include "AllocStr.h"
  14. #include <libraries/DosExtens.h>  /* for Process definition */
  15. #include <Workbench/Startup.h>    /* for WBStartup definition */
  16. #include <Workbench/WorkBench.h>  /* for DiskObject definition */
  17. #include <Proto/Icon.h>
  18. #include <string.h>
  19.  
  20. extern struct Process *MyProc;         /* This Process */
  21. extern BPTR            WorkDirLock;    /* The current directory */
  22.  
  23. extern void Warn(char *);         /* routine to notify user of error */
  24.  
  25. /*-----------------------------------------------------*/
  26.  
  27. static void
  28. RunCLI( EItem )
  29.   struct ExtMenuItem *EItem;
  30. /* execute a CLI command using the appropiate console
  31. ** for command (either a default or commands own).
  32. */
  33. {
  34.   struct ProcessControlBlock *PCB=NULL; /* structure for Arp's ASynchRun */
  35.   BPTR    NewDirLock=NULL;              /* Directory Lock for CD */
  36.   long    CLI=0;                        /* result code - CLI number used */
  37.   char    buf[256], *ConWin, *Error;
  38.  
  39.   DB( FPrintf(DBWindow, "CLIRun -> `%s'\n", EItem->Cmd); )
  40.  
  41.     /* is new Directory Update the directory */
  42.   if( EItem->Directory ) {
  43.     if( !( NewDirLock = Lock(EItem->Directory, ACCESS_READ) ) ) {
  44.       SPrintf(buf, "Unable to Find Directory `%s' ", EItem->Directory);
  45.       Warn(buf);  return;
  46.     }
  47.     CurrentDir(NewDirLock);
  48.   }
  49.  
  50.  
  51.   PCB = (struct ProcessControlBlock *)
  52.      AllocMem( sizeof(struct ProcessControlBlock), MEMF_CLEAR|MEMF_PUBLIC);
  53.  
  54.   if( !PCB )
  55.     CLI = PR_NOMEM;                /* failed to allocate PCB struct */
  56.   else {
  57.      /* allocate appropiate stack and prioity */
  58.     PCB->pcb_StackSize = EItem->Stack;       /* Stack */
  59.     PCB->pcb_Pri       = EItem->Pri;         /*  Pri  */
  60.  
  61.     ConWin = ( EItem->Console ? EItem->Console : M->Console );
  62.     switch( EItem->Mode ) {
  63.     case 'C':                              /* CLI mode - Open a Console */
  64.       PCB->pcb_Control  =  PRF_STDIO;
  65.       PCB->pcb_Console.pcb_ConName = (BYTE *) ConWin;
  66.       break;
  67.     case 'R':                              /* RunBack - No File Handles */
  68.       PCB->pcb_Control = PRF_SAVEIO;
  69.       break;
  70.     case 'S':                              /* Script - New Shell */
  71.       PCB->pcb_Control = INTERACTIVE_SHELL;
  72.     }
  73.  
  74.     DB( FPrintf(DBWindow, "-- ASynchRun()\n"); )
  75.     CLI = ( EItem->Mode == 'S' )
  76.           ? ASyncRun( ConWin, EItem->Cmd, PCB)       /* interactive shell */
  77.           : ASyncRun( EItem->Cmd, EItem->Args, PCB); /* run command */
  78.   }
  79.  
  80.     /* Handle Errors */
  81.   if( CLI<0 ) {       /* negitive result -- Report Appropiate Error */
  82.     switch( CLI ) {
  83.     case PR_NOSTDIO:  Error = "%s: Unable to open Console"; break;
  84.     case PR_NOFILE:   Error = "%s: Unknowen Command `%s'"; break;
  85.     case PR_NOMEM:    Error = "%s: Not Enough Memory"; break;
  86.     case PR_NOSLOT:   Error = "%s: Task Table Full"; break;
  87.     case PR_NOINPUT:
  88.     case PR_NOOUTPUT: Error = "%s: IO Error on Console"; break;
  89.     case PR_SCRIPT:   Error = "%s: Script run using wrong mode"; break;
  90.     default:          Error = "%s: ASynchRun Failed on `%s' (%ld)";
  91.     }
  92.     SPrintf(buf, Error, VERSION, EItem->Cmd, CLI);
  93.     Warn(buf);
  94.   }
  95.  
  96.   if( PCB )
  97.     FreeMem( PCB, sizeof(struct ProcessControlBlock) );
  98.   if( EItem->Directory )            /* Return to the Working Directory */
  99.     UnLock( CurrentDir( WorkDirLock ) );
  100.   DB( FPrintf(DBWindow, "---- Done ----\n"); )
  101. }
  102.  
  103.  
  104. /*--------------------------------------------------*/
  105. /* procedures to support running WorkBench programs */
  106.  
  107.  
  108. extern                   WBProcesses;  /* WB processes currently running */
  109. extern struct MsgPort   *WBReplyPort;  /* Port for Process to reply to */
  110.  
  111.  
  112. void
  113. WBFree( StartMsg )
  114.   struct WBStartup *StartMsg;
  115. /*  Free up space used by a workbench startup message.  Called whenever
  116.  *  a workbench program replies to the startup message, and whenever
  117.  *  `WBRun()' gets an error
  118.  */
  119. {
  120.   register int i;
  121.  
  122.   if( StartMsg ) {
  123.     if( WBProcesses ) /* decrement number of processes */
  124.       WBProcesses--;
  125.     if( StartMsg->sm_ArgList ) {
  126.       for (i=0; i<StartMsg->sm_NumArgs; i++) {
  127.         if( StartMsg->sm_ArgList[i].wa_Lock )
  128.           UnLock(StartMsg->sm_ArgList[i].wa_Lock);
  129.         if( StartMsg->sm_ArgList[i].wa_Name )
  130.           FreeStr(StartMsg->sm_ArgList[i].wa_Name);
  131.       }
  132.       FreeMem( StartMsg->sm_ArgList,
  133.                  sizeof(struct WBArg) *StartMsg->sm_NumArgs );
  134.     }
  135.     if( StartMsg->sm_Segment )
  136.       UnLoadSeg(StartMsg->sm_Segment);
  137.     if( StartMsg->sm_ToolWindow )
  138.       FreeStr(StartMsg->sm_ToolWindow );
  139.     FreeMem( StartMsg , sizeof(struct WBStartup) );
  140.   }
  141. }
  142.  
  143.  
  144. static void
  145. RunWB( EItem )
  146.   struct ExtMenuItem *EItem;
  147. /* load and run a workbench program
  148.  * This routine is errored in the following ways
  149.  *   1/ No ToolTypes are handled
  150.  *   2/ The TOOL for a PROJECT is expected to have an icon (it may not!).
  151.  *   3/ Current Directory is that of the TOOL not the PROJECT or
  152.  *   4/ User can't select the Current Directory to use (should he?).
  153.  *                                                      -- Anthony Thyssen
  154.  */
  155. {
  156.   BPTR                DirLock = NULL, OldLock = NULL, IconLock;
  157.   struct WBStartup   *StartMsg = NULL;
  158.   struct DiskObject  *DiskObject = NULL;
  159.   char               *Name, buf[128];
  160.   BOOL                Error = TRUE;      /* assume the worst */
  161.   int                 I;
  162.  
  163.     /* Lock Projects Directory */
  164.   Name = BaseName(EItem->Cmd);
  165.   strcpy(buf, EItem->Cmd);
  166.   strcat(buf, ".info");  /* this will be present the project may not! */
  167.   if( !(IconLock = Lock(buf, ACCESS_READ) ) ) {
  168.     SPrintf(buf, "Can't locate `%s.info'", Name);
  169.     goto finish;
  170.   }
  171.   DirLock = ParentDir(IconLock);
  172.   UnLock(IconLock);
  173.   if( !DirLock ) {
  174.     SPrintf(buf, "Directory invalid for `%s'", EItem->Cmd);
  175.     goto finish;
  176.   }
  177.  
  178.     /* Load Icon */
  179.   OldLock = CurrentDir( DirLock );
  180.   if( !(DiskObject = GetDiskObject(Name)) ) {
  181.     SPrintf(buf, "Can't locate `%s.info'", Name);
  182.     goto finish;
  183.   }
  184.   switch( DiskObject->do_Type ) {
  185.   case WBTOOL:    I=1; break; /* just the tool */
  186.   case WBPROJECT: I=2; break; /* tool & project */
  187.   default:
  188.     SPrintf(buf, "`%s.info' is not a TOOL or PROJECT!", Name);
  189.     goto finish;
  190.   }
  191.  
  192.     /* allocate the startup message */
  193.   if( !(StartMsg = (struct WBStartup *)
  194.            AllocMem( sizeof(struct WBStartup), MEMF_PUBLIC|MEMF_CLEAR))) {
  195.     SPrintf(buf, "%s: Not Enough Memory", VERSION);
  196.     goto finish;
  197.   }
  198.   StartMsg->sm_NumArgs = I;
  199.   if( !(StartMsg->sm_ArgList = (struct WBArg *)
  200.          AllocMem( sizeof(struct WBArg)*I, MEMF_PUBLIC|MEMF_CLEAR)) ) {
  201.     SPrintf(buf, "%s: Not Enough Memory", VERSION);
  202.     goto finish;
  203.   }
  204.  
  205.   I--; /* Fill in the Last WBArg the TOOL/Project we referenced */
  206.   StartMsg->sm_ArgList[I].wa_Lock = DirLock;
  207.   StartMsg->sm_ArgList[I].wa_Name = AllocStr(Name);
  208.  
  209.   if( I ) {   /* if WBPROJECT - Fill out the Tool */
  210.     StartMsg->sm_ArgList->wa_Lock = DupLock(DirLock); /* same as project */
  211.     StartMsg->sm_ArgList->wa_Name = AllocStr(DiskObject->do_DefaultTool);
  212.     Name = StartMsg->sm_ArgList->wa_Name;    /* Set the new name */
  213.   }
  214.  
  215.     /* initialize rest of startup message */
  216.   StartMsg->sm_Message.mn_ReplyPort = WBReplyPort;
  217.   StartMsg->sm_Message.mn_Length = sizeof(struct WBStartup);
  218.   StartMsg->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
  219.   StartMsg->sm_ToolWindow = AllocStr(DiskObject->do_ToolWindow);
  220.  
  221.     /* Insure a decent stack size, some progs have this set to zero */
  222.   if( DiskObject->do_StackSize < EItem->Stack )
  223.     DiskObject->do_StackSize = EItem->Stack;
  224.  
  225.  
  226.     /* load in the program */
  227.   if( !(StartMsg->sm_Segment = LoadPrg(Name)) ) {
  228.     SPrintf(buf, "Unable to Load `%s'", Name);
  229.     goto finish;
  230.   }
  231.  
  232.   /* create process */
  233.   if( !(StartMsg->sm_Process = CreateProc( Name, (LONG)EItem->Pri,
  234.           StartMsg->sm_Segment, DiskObject->do_StackSize)) ) {
  235.     SPrintf(buf, "Can't execute `%s'", Name);
  236.     goto finish;
  237.   }
  238.  
  239.     /* everything's ok -- start 'er up */
  240.   PutMsg( StartMsg->sm_Process , (struct Message *)StartMsg );
  241.   Error = FALSE;
  242.   WBProcesses++;        /* keep track of unreplied startup messages */
  243.  
  244. finish:
  245.   if( DiskObject ) FreeDiskObject( DiskObject );
  246.   if( OldLock )    CurrentDir( OldLock );
  247.   if( Error ) {
  248.     if( StartMsg ) WBFree( StartMsg );
  249.     Warn(buf);
  250.   }
  251. }
  252.  
  253.  
  254. /*-------------------------------------------------*/
  255.  
  256. void
  257. RunItem( EItem )
  258.   struct ExtMenuItem *EItem;
  259. {
  260.   switch( EItem->Mode ) {
  261.   case 'R':
  262.   case 'C':
  263.   case 'S':  RunCLI( EItem ); break;
  264.   case 'W':  RunWB( EItem ); break;
  265.   }
  266. }
  267.  
  268.