/* Copyright ) Darin Johnson, 1989 */ /* DoRun.c -- I met her on a Monday, and my heart stood still... */ #include #include #include #include #include #include #include #include #include #include "mymenu.h" #ifdef AZTEC_C #define strlen _BUILTIN_strlen #define strcpy _BUILTIN_strcpy #endif #ifdef DO_PATH #define CMDSIZ 256 #define CBUFSZ 80 #endif extern struct Process *MyProcess; /* text to put into autorequesters */ struct IntuiText err_nocmd = { 0,1,JAM2, 20,10, NULL, (UBYTE*)"MyMenu: can't execute command", NULL }; struct IntuiText err_nomem = { 0,1,JAM2, 20,10, NULL, (UBYTE*)"MyMenu: out of memory!", NULL }; struct IntuiText err_noinfo = { 0,1,JAM2, 20,10, NULL, (UBYTE*)"MyMenu: can't open info file", NULL }; struct IntuiText err_notool = { 0,1,JAM2, 20,10, NULL, (UBYTE*)"MyMenu: not a tool or project", NULL }; struct IntuiText req_neg = { 0,1,JAM2, 7,3, NULL, (UBYTE*)"Aw, shucks", NULL }; /* process a menu item */ int run_item(item) struct ext_MenuItem *item; { if (item->cmd) { if (item->type == 'C') { do_clirun(item->cmd, item->args); } #ifdef DO_WB else if (item->type == 'W') { do_wbrun(item->cmd); } #endif } } #ifdef DO_PATH char *FindIt(); #endif /* execute a CLI command */ do_clirun(cmd, args) char *cmd, *args; { struct FileHandle *NilFh, *Open(); register char *buf; register short siz; #ifdef DO_PATH cmd = FindIt(cmd); #endif if (cmd==NULL) { AutoRequest(NULL, &err_nocmd, NULL, &req_neg, 0,0,300,60); return; } siz = 32 + strlen(cmd); if (args) siz += strlen(args); buf = (char *)AllocMem(siz, MEMF_PUBLIC); if (buf==NULL) { AutoRequest(NULL, &err_nomem, NULL, &req_neg, 0,0,300,60); return; } strcpy(buf, "RUN NIL: \""); strcat(buf, cmd); strcat(buf, "\" NIL: "); if (args) strcat(buf, args); NilFh = Open("NIL:", MODE_NEWFILE); if (NilFh) { Execute(buf, NULL, NilFh); Close(NilFh); } FreeMem(buf, siz); } /* procedures to support running WorkBench programs */ #ifdef DO_WB extern int wb_cnt; extern struct MsgPort *wb_reply_port; /* create (and allocate) a copy of a string */ char *copystr(str) { char *tmpstr; if (!str) return NULL; tmpstr = (char *)AllocMem(strlen(str)+1, MEMF_PUBLIC); strcpy(tmpstr, str); return tmpstr; } /* Free up space used by a workbench startup message. Called whenever a workbench program replies to the startup message, and whenever do_wbrun() gets an error */ wbfree(WBStartup) struct WBStartup *WBStartup; { register BPTR lock; register int i; register char *cp; if (WBStartup != NULL) { if (WBStartup->sm_ArgList != NULL) { for (i=0; ism_NumArgs; i++) { if ((lock=WBStartup->sm_ArgList[i].wa_Lock) != NULL) { UnLock(lock); } if ((cp=WBStartup->sm_ArgList[i].wa_Name) != NULL) FreeMem(cp, strlen(cp)+1); } FreeMem(WBStartup->sm_ArgList, sizeof(struct WBArg)*WBStartup->sm_NumArgs); } if (WBStartup->sm_Segment != NULL) { UnLoadSeg(WBStartup->sm_Segment); } if ((cp=WBStartup->sm_ToolWindow) != NULL) 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 */ split_path(path, dir_lock, name) char *path, **name; BPTR *dir_lock; { register char *p; register BPTR lock; for (p=path, *name=path; *p; p++) if (*p == '/' || *p == ':') *name = p+1; lock = (BPTR)Lock(path, ACCESS_READ); if (lock) { *dir_lock = (BPTR)ParentDir(lock); UnLock(lock); } else { *dir_lock = (BPTR)DupLock(MyProcess->pr_CurrentDir); } } /* load and run a workbench program */ int do_wbrun(cmd) char *cmd; { BPTR lock, oldlock; struct WBStartup *WBStartup; struct DiskObject *disk_object; char argc, *name, buf[128]; char error; disk_object = WBStartup = NULL; lock = oldlock = NULL; name = NULL; error = TRUE; /* assume the worst */ /* allocate the startup message */ if ((WBStartup = (struct WBStartup *)AllocMem(sizeof(struct WBStartup), MEMF_PUBLIC|MEMF_CLEAR)) == NULL) { AutoRequest(NULL, &err_nomem, NULL, &req_neg, 0,0,300,60); return TRUE; /* don't go to finish:, nothing allocated yet */ } #ifdef DO_PATH if ((cmd = FindIt(cmd)) == NULL) goto finish; #endif /* find the directory and name of the program to run */ split_path(cmd, &lock, &name); if (lock == NULL) { AutoRequest(NULL, &err_nocmd, NULL, &req_neg, 0,0,300,60); goto finish; } /* try to load in the .info file */ oldlock = (BPTR)CurrentDir(lock); if ((disk_object = GetDiskObject(name)) == NULL) { AutoRequest(NULL, &err_noinfo, NULL, &req_neg, 0,0,300,60); 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)) == NULL) { AutoRequest(NULL, &err_nomem, NULL, &req_neg, 0,0,300,60); 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)) == NULL) { AutoRequest(NULL, &err_nomem, NULL, &req_neg, 0,0,300,60); 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); split_path(buf, &lock, &name); FreeDiskObject(disk_object); CurrentDir(lock); if ((disk_object = GetDiskObject(name)) == NULL) { AutoRequest(NULL, &err_noinfo, NULL, &req_neg, 0,0,300,60); goto finish; } /* we have to have a tool at this point - or else */ if (disk_object->do_Type != WBTOOL) { AutoRequest(NULL, &err_notool, NULL, &req_neg, 0,0,300,60); 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 = wb_reply_port; 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)LoadSeg(name)) == NULL) { AutoRequest(NULL, &err_nocmd, NULL, &req_neg, 0,0,300,60); goto finish; } /* create process */ if ((WBStartup->sm_Process = (struct MsgPort *)CreateProc(name, 0, WBStartup->sm_Segment, disk_object->do_StackSize)) == NULL) { AutoRequest(NULL, &err_nocmd, NULL, &req_neg, 0,0,300,60); goto finish; } /* everything's ok -- start 'er up */ PutMsg(WBStartup->sm_Process, WBStartup); error = FALSE; wb_cnt++; /* keep track of unreplied startup messages */ finish: if (disk_object) FreeDiskObject(disk_object); if (oldlock) CurrentDir(oldlock); if (error) wbfree(WBStartup); return error; } #endif #ifdef DO_PATH /* This section is largely taken from RunBack (which was largely taken from which.c by Carolyn Scheppner). This handles path searching. */ /***** currently these routines can cause guru's Run a workbench program, and then run a program that uses the path searching - often causes a Guru, but can't tell why. If the wbfree() does NOT free its locks, then it doesn't guru. *****/ static char sbuf[CMDSIZ]; /* search for a command in our path */ char *FindIt(command) char *command; { BOOL getPath(); struct Path *path; struct FileInfoBlock *fib; BPTR lock, startcd; BOOL Found, InitialCD; /* Were we given full path in command name (':' in name) ? */ { register char *p; for (p=command; *p; p++) { if (*p == ':') { lock = (BPTR)Lock(command,ACCESS_READ); if (lock==NULL) return NULL; /* command not found */ UnLock(lock); return command; } } } /* allocate this for Examine() calls */ fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR); if (fib == NULL) return NULL; /* Check current directory */ Found = getPath(command, fib, sbuf); /* Check along paths */ if (!Found) { InitialCD = TRUE; for (path = MM->CLI_path; (path) && (!Found); path = path->path_Next) { /* CD to each path */ lock = (BPTR)CurrentDir(path->path_Lock); if (InitialCD) { startcd = lock; InitialCD = FALSE; } /* See if command is there */ Found = getPath(command, fib, sbuf); } /* If we CD'd anywhere, restore initial CD */ if (!InitialCD) CurrentDir(startcd); } /* Check C: */ if (!Found) { char cbuf[CBUFSZ]; strcpy(cbuf,"C:"); strcpy(&cbuf[2], command); Found = getPath(cbuf, fib, sbuf); } /* Free fib */ if (fib != NULL) FreeMem(fib, sizeof(struct FileInfoBlock)); if (Found) return(sbuf); else return(NULL); } /* see if command is in current directory, if so, return path name in 'buf' */ BOOL getPath(command,fib,buf) char *command; struct FileInfoBlock *fib; char *buf; { BPTR lock; BOOL success = FALSE; if (lock = (BPTR)Lock(command, ACCESS_READ)) { if (Examine(lock, fib)) { buildPath(lock, fib, buf); success = TRUE; } UnLock(lock); } return(success); } /* builds up a path name from 'inlock' and returns it in 'buf' */ buildPath(inlock,fib,buf) BPTR inlock; struct FileInfoBlock *fib; char *buf; { int i; BPTR lock, oldlock; buf[0] = NULL; lock = inlock; /* follow path up, building up name as we go */ while (lock) { if (Examine(lock, fib)) { if (fib->fib_FileName[0] > ' ') { if (buf[0]) insert(buf,"/"); insert(buf,fib->fib_FileName); } } oldlock = lock; lock = (BPTR)ParentDir(lock); /* make sure we don't unlock the lock passed to us */ if (oldlock != inlock) UnLock(oldlock); } /* fix up path name */ if (fib->fib_FileName[0] > ' ') { register char *p; for (p=buf; *p; p++) { if (*p == '/') { *p = ':'; break; } } } else insert(buf,"RAM:"); /* why? */ } /* insert 's' at the beginning of 'buf' */ insert(buf,s) char *buf,*s; { char tmp[CMDSIZ]; strcpy(tmp, buf); strcpy(buf, s); strcpy(&buf[strlen(s)], tmp); } #endif