/* * starttools.c V1.5 * * CLI & WB startup procedure * * (c) 1991 by Stefan Becker * */ #include "ToolManager.h" #define CMDLINELEN 4096 /* Structure for path list */ struct PathList { BPTR NextPath; /* Pointer to next PathList */ BPTR PathLock; /* Lock on directory */ }; /* Build a path list from a string */ static BOOL BuildPathList(struct PathList **pla, struct PathList **plc, char *s) { /* Path string valid? */ if (s) { char *ps; /* Yes, copy path string */ if (ps=strdup(s)) { struct FileInfoBlock *fib; /* Get memory for FIB */ if (fib=calloc(sizeof(struct FileInfoBlock),1)) { char *cp1,*cp2=ps; struct PathList *pl1=*plc,*pl2=NULL; /* For every path part */ while (cp1=cp2) { /* Search next path part */ cp2=strchr(cp1,','); if (cp2) { *cp2='\0'; /* Add string end character */ cp2++; /* Move to next character */ } /* Get memory for path list entry */ if (!pl2 && !(pl2=AllocVec(sizeof(struct PathList),MEMF_PUBLIC|MEMF_CLEAR))) { free(fib); free(ps); return(FALSE); } /* Get lock */ if (pl2->PathLock=Lock(cp1,SHARED_LOCK)) /* Is it a directory? */ if (Examine(pl2->PathLock,fib) && (fib->fib_DirEntryType>0)) { /* Yes, it is a directory, append it to the list. Head of list? */ if (*pla) { pl1->NextPath=MKBADDR(pl2); /* No, chain new entry into list */ pl1=pl2; } else *pla=pl1=pl2; /* Yes, start of list */ /* Invalidate pointer, next time a new PathList will be allocated */ pl2=NULL; } else UnLock(pl2->PathLock); /* No, it is a file */ } *plc=pl1; /* Save end of list */ if (pl2) FreeVec(pl2); /* Last Lock() failed, free memory */ free(fib); } free(ps); } } return(TRUE); } /* Start tool as a CLI process */ static BOOL StartCLITool(struct AppMessage *msg, struct ToolNode *tn, char *name) { BPTR fl,ofh,ifh; /* AmigaDOS file handles */ struct MsgPort *newct=NULL; /* New ConsoleTask pointer */ struct PathList *pla=NULL,*plc=NULL; char *cmd; /* Buffer for command line */ struct WBArg *wa=msg->am_ArgList; int cmdlen; /* Command line length */ int i; char dir[NAMELEN]; /* Get memory for command line */ if (!(cmd=malloc(CMDLINELEN))) return(FALSE); fl=CurrentDir(tn->tn_DirLock); /* Change to tool's directory */ strcpy(cmd,name); /* Command name first */ cmdlen=strlen(cmd); for (i=msg->am_NumArgs; i; i--,wa++) { char *cp; int namelen; if (!wa->wa_Lock) continue; /* Skip arguments which don't support locks! */ if (cmdlen>CMDLINELEN-2) break; /* Append a space for each parameter */ strcat(cmd," "); cmdlen++; /* Build parameter from Lock & name */ if (SameLock(tn->tn_DirLock,wa->wa_Lock)==LOCK_SAME) cp=wa->wa_Name; else { if (!NameFromLock(wa->wa_Lock,dir,NAMELEN)) continue; if (!AddPart(dir,wa->wa_Name,NAMELEN)) continue; cp=dir; } namelen=strlen(cp); if (strchr(cp,' ')) /* Special case: Space in a filename */ if (namelen>NAMELEN-3) break; else { strins(cp,"\""); /* Set parameter in double quotes */ strcat(cp,"\""); namelen+=2; } if (cmdlen+namelen>CMDLINELEN-2) break; strcat(cmd,cp); /* Append parameter */ cmdlen+=namelen; /* New command line length */ } /* Open input & output file */ if (tn->tn_Flags&TNFLAGS_COUT) if (tn->tn_OutFile) ofh=Open(tn->tn_OutFile,MODE_NEWFILE); /* Use tool output file */ else ofh=Open(CLIOutputFile,MODE_NEWFILE); /* Use standard output file */ else ofh=Open("NIL:",MODE_NEWFILE); /* Ignore output */ if (!ofh) goto ste1; /* Is the output file an interactive file? */ if (IsInteractive(ofh)) { struct MsgPort *oldct; /* Old ConsoleTask pointer */ /* Yes. We need the same file as input file for CTRL-C/D/E/F redirection */ /* Set our ConsoleTask to the new output file, so that we can re-open it */ newct=((struct FileHandle *) BADDR(ofh))->fh_Type; oldct=SetConsoleTask(newct); /* Open the new input file (Now ifh points to the same file as ofh) */ ifh=Open("CONSOLE:",MODE_OLDFILE); /* Change back to old ConsoleTask */ SetConsoleTask(oldct); } else /* Non-interactive output, open dummy input file */ ifh=Open("NIL:",MODE_OLDFILE); if (!ifh) goto ste2; /* Build path list */ if (!BuildPathList(&pla,&plc,tn->tn_Path)) goto ste3; /* Tool path first */ if (!BuildPathList(&pla,&plc,GlobalPath)) goto ste3; /* Start tool */ if (SystemTags(cmd,SYS_Output,ofh, SYS_Input,ifh, SYS_Asynch,TRUE, /* Run tools asynchronously */ SYS_UserShell,TRUE, /* Use user specified shell */ NP_StackSize,tn->tn_Stack, NP_Path,MKBADDR(pla), NP_ConsoleTask,newct, TAG_DONE)==-1) goto ste3; /* Tool started */ CurrentDir(fl); /* Change to old directory */ free(cmd); return(TRUE); ste3: if (pla) /* Free path list */ { struct PathList *pl1=pla,*pl2; do { pl2=BADDR(pl1->NextPath); UnLock(pl1->PathLock); FreeVec(pl1); } while (pl1=pl2); } Close(ifh); ste2: Close(ofh); ste1: CurrentDir(fl); /* Change to old directory */ free(cmd); return(FALSE); } /* Start tool as a WB process */ static BOOL StartWBTool(struct AppMessage *msg, struct ToolNode *tn, char *name) { BPTR fl; /* AmigaDOS file handle */ register struct WBStartup *wbs; /* WBStartup message for tool */ struct DiskObject *tdob; /* Tool icon */ LONG ssize; /* StackSize, default */ struct MsgPort *proc; /* Process descriptor for tool */ /* struct Process *proc; Process descriptor for CreateNewProc */ struct WBArg *wbad,*wbas; /* Pointers to WB arguments */ char *proname=NULL; /* Name of Project icon */ int i; /* Allocate memory for WBStartup */ if (!(wbs=calloc(sizeof(struct WBStartup)+ sizeof(struct WBArg)*(msg->am_NumArgs+2),1))) return (FALSE); /* Change to tool's directory */ fl=CurrentDir(tn->tn_DirLock); /* Is it a project? */ if (tdob=GetDiskObject(name)) if (tdob->do_Type==WBPROJECT) { proname=name; /* Save original name */ name=strdup(tdob->do_DefaultTool); /* Get name of default tool */ FreeDiskObject(tdob); if (!name) goto e1; /* Enough memory? */ tdob=GetDiskObject(name); /* Get icon of the default tool */ } /* Is it a tool? */ ssize=tn->tn_Stack; if (tdob) { if (tdob->do_Type==WBTOOL) /* Only tools supply this information */ { if (tdob->do_ToolWindow) wbs->sm_ToolWindow=strdup(tdob->do_ToolWindow); if (tdob->do_StackSize>ssize) ssize=tdob->do_StackSize; } FreeDiskObject(tdob); } /* Load tool code */ /* if (!(wbs->sm_Segment=NewLoadSeg(name,NULL))) goto e2; */ if (!(wbs->sm_Segment=LoadSeg(name))) goto e2; /* Build WBStartup message */ /* wbs->sm_Message.mn_Node.ln_Type=NT_MESSAGE; PutMsg() does this for us! */ wbs->sm_Message.mn_ReplyPort=MyMP; wbs->sm_Message.mn_Length=sizeof(struct WBStartup); wbs->sm_NumArgs=msg->am_NumArgs+1; wbs->sm_ArgList=wbs+1; /* WBArg array starts after WBStartup */ /* Initialize WBArg pointers */ wbas=msg->am_ArgList; wbad=wbs->sm_ArgList; /* 1. argument is the tool itself! */ if (!(wbad->wa_Lock=DupLock(tn->tn_DirLock))) goto e3; if (!(wbad->wa_Name=strdup(name))) goto e4; wbad++; /* If tool is a project, add it as 2. parameter to the WBArg list */ if (proname) { if (!(wbad->wa_Lock=DupLock(tn->tn_DirLock))) goto e4; if (!(wbad->wa_Name=strdup(proname))) goto e4; wbad++; wbs->sm_NumArgs++; } /* Copy WB arguments */ for (i=msg->am_NumArgs; i; i--,wbas++,wbad++) { if (!(wbad->wa_Lock=DupLock(wbas->wa_Lock))) { wbad--; /* Skip parameters, which don't support a lock */ wbs->sm_NumArgs--; continue; /* Next parameter */ } /* Sanity check for name string... Enforcer is watching you! */ if (!wbas->wa_Name || !(wbad->wa_Name=strdup(wbas->wa_Name))) goto e4; } /* Create process */ if (!(wbs->sm_Process=CreateProc(wbs->sm_ArgList->wa_Name,0,wbs->sm_Segment, ssize))) goto e4; /* if (!(proc=CreateNewProcTags(NP_Seglist,wbs->sm_Segment, NP_FreeSeglist,TRUE, Maybe someday I will know NP_StackSize,ssize, what Tags I need to make NP_Name,wbs->sm_ArgList->wa_Name, CreateNewProc() behave NP_CloseInput,FALSE, like CreateProc() NP_CloseOutput,FALSE, TAG_DONE))) goto e4; */ /* Send WBStartup message to tool */ /* wbs->sm_Process=&proc->pr_MsgPort; for CreateNewProc() */ PutMsg(wbs->sm_Process,(struct Message *) wbs); if (proname) free(name); /* If project, then free default tool name */ CurrentDir(fl); /* Change to old directory */ wbactive++; /* Tool started! */ return(TRUE); /* An error occurred. Free all resources */ e4: wbas=wbs->sm_ArgList; for (i=wbs->sm_NumArgs; i; i--,wbas++) { UnLock(wbas->wa_Lock); if (wbas->wa_Name) free(wbas->wa_Name); } e3: UnLoadSeg(wbs->sm_Segment); e2: if (proname) free(name); e1: CurrentDir(fl); free(wbs); return(FALSE); } /* Start a tool with arguments */ void StartTool(struct ToolNode *tn, struct AppMessage *msg) { BOOL rc=TRUE; char *cp; struct AppMessage emsg; /* No Parameters? */ if (!msg || tn->tn_Flags&TNFLAGS_NARG) { emsg.am_NumArgs=0; /* Dummy AppMessage has 0 arguments */ msg=&emsg; /* Replace pointer to real message */ } /* Get tool name */ if (!(cp=tn->tn_RealName)) cp=tn->tn_Node.ln_Name; /* Tool type? */ switch(tn->tn_Type) { case TNTYPE_CLI: rc=StartCLITool(msg,tn,cp); break; case TNTYPE_WB: rc=StartWBTool(msg,tn,cp); break; } if (!rc) DisplayBeep(NULL); /* An error occured */ }