home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-17 | 8.0 KB | 347 lines | [TEXT/R*ch] |
- // DChildApp.cpp
-
-
- #include "DClap.h"
- #include "DChildApp.h"
-
-
- #ifdef WIN_MAC
- // undef some conflicts b/n Types.h && NlmTypes
- #undef Handle
- #undef true
- #undef false
- //#undef Boolean
- #include <AppleEvents.h>
- #include <Processes.h>
- //#define Boolean Nlm_Boolean
- #endif
-
- //class DChildFile : public DFile
-
-
- DChildFile::DChildFile( const char* filename, short kind, Boolean deleteWhenDone,
- short doneAction, const char* openmode, const char* ftype, const char* fcreator) :
- DFile( filename, openmode, ftype, fcreator),
- fAction(doneAction), fKind(kind), fDelete( deleteWhenDone)
- {
- if (!openmode) switch (fKind) {
- case kInput:
- case kStdin: fMode= StrDup("r"); break; //?? we really open "w" not "r" ??
- case kOutput: fMode= StrDup("r"); break; //?? we really open "r" not "w" !?
- case kStdout: fMode= StrDup("r"); break; // was "a", ??? "w" or "a"
- case kStderr: fMode= StrDup("r"); break; // was "a", ??? "w" or "a"
- }
- }
-
- DChildFile::~DChildFile()
- {
- if (fDelete) this->Delete();
- }
-
- void DChildFile::ClearStorage()
- {
- this->Close();
- if (fDelete) this->Delete();
- }
-
-
-
-
-
- //class DChildApp : public DTaskMaster
-
- DChildApp::DChildApp() :
- DTaskMaster(0),
- fName(NULL), fCmdline(NULL),
- fStdin(NULL), fStdout(NULL), fStderr(NULL),
- fLaunched(0), fResult(0), fReusable(false),
- fProcessNum(0), fFiles(NULL)
- {
- if (!DChildAppManager::gChildList) DChildAppManager::gChildList= new DList();
- DChildAppManager::gChildList->InsertLast( this); // do this here so caller doesn't forget
- }
-
-
- DChildApp::DChildApp( char* appname, char* cmdline,
- Boolean showStdout, char* Stdinfile, Boolean showStderr) :
- DTaskMaster(0),
- fName(NULL), fCmdline(NULL),
- fStdin(NULL), fStdout(NULL), fStderr(NULL),
- fLaunched(0), fResult(0), fReusable(false),
- fProcessNum(0), fFiles(NULL)
- {
- fName= StrDup( appname);
- fCmdline= StrDup( cmdline);
- fFiles= new DList();
-
- // this is called for launching docs as well as apps,
- // don't do the stdout/stderr stuff if this is doc
- if (showStdout) AddFile( DChildFile::kStdout, NULL);
- if (showStderr) AddFile( DChildFile::kStderr, NULL);
- if (Stdinfile) AddFile( DChildFile::kStdin, Stdinfile);
-
- if (!DChildAppManager::gChildList) DChildAppManager::gChildList= new DList();
- DChildAppManager::gChildList->InsertLast( this); // do this here so caller doesn't forget
- }
-
-
- #if 0
- DChildApp* DChildAppManager::newChildApp( char* appname, char* cmdline,
- Boolean Stdout, char* Stdinfile, Boolean Stderr)
- {
- DChildApp* aChild= new DChildApp( char* appname, char* cmdline,
- Boolean Stdout, char* Stdinfile, Boolean Stderr);
- gChildList->InsertLast( aChild); // !! must do this here or ?? in DChildapp constructors?
- return aChild;
- }
- #endif
-
-
- DChildApp::~DChildApp()
- {
- MemFree( fName);
- MemFree( fCmdline);
- if (fFiles) {
- short i, n= fFiles->GetSize();
- for (i=0; i<n; i++) {
- DChildFile* afile= (DChildFile*) fFiles->At(i);
- delete afile;
- }
- delete fFiles;
- }
- DChildAppManager::gChildList->Delete( this); //need here to balance constructor Insert()
- }
-
-
-
- void DChildApp::AddInputBuffer( short filekind, char* buffer, ulong buflen)
- {
- char namestore[512], *name;
- DChildFile* aFile;
- name= gFileManager->TempFilename(namestore);
- switch (filekind) {
- case DChildFile::kInput:
- case DChildFile::kStdin:
- aFile= new DChildFile( name, filekind, true, DChildFile::kNoAction);
- break;
- default:
- return;
- }
- if (aFile) {
- aFile->Open("w");
- aFile->WriteData( buffer, buflen);
- aFile->Close();
- aFile->SetMode("r");
- this->AddFile( aFile);
- }
- }
-
- void DChildApp::AddFile( DChildFile* aFile)
- {
- // ?? need to check if fFiles already has one of stdio types ??
- fFiles->InsertLast( aFile);
- switch (aFile->fKind) {
- case DChildFile::kStdin:
- fStdin= aFile->GetName();
- break;
- case DChildFile::kStdout:
- fStdout= aFile->GetName();
- break;
- case DChildFile::kStderr:
- fStderr= aFile->GetName();
- break;
- }
- }
-
- void DChildApp::AddFile( short filekind, char* name)
- {
- char namestore[512];
- DChildFile* aFile;
- if (!name) {
- if (filekind == DChildFile::kStdin || filekind == DChildFile::kInput) return;
- name= gFileManager->TempFilename(namestore);
- }
-
- switch (filekind) {
- case DChildFile::kInput:
- case DChildFile::kStdin:
- aFile= new DChildFile( name, filekind, false, DChildFile::kNoAction);
- break;
-
- case DChildFile::kOutput:
- case DChildFile::kStdout:
- aFile= new DChildFile( name, filekind, false);
- break;
- case DChildFile::kStderr:
- aFile= new DChildFile( name, filekind, true);
- break;
- }
- this->AddFile( aFile);
- }
-
-
-
- #ifdef WIN_MAC
- extern "C" ProcessSerialNumber gChildProcessSN;
- #else
- extern "C" long gChildProcessSN;
- #endif
-
- class DBurialTask : public DTask {
- public:
- DBurialTask( long processnum, DTaskMaster* itsSource) :
- DTask( processnum, DTask::kOtherTask, itsSource) {}
- virtual void DoIt() { DChildAppManager::BuryDeadChildApp(fNumber); }
- };
-
-
- Boolean DChildApp::Launch()
- {
- // ?? want special handling for stdin/stdout/stderr files !!
- // !! must assume OtherFiles are already handled, either in cmdline or by child app !!
- fResult= 0;
- if (fName || fCmdline) {
- fLaunched++;
- fResult= Dgg_LaunchApp( fName, fCmdline, (char*)fStdin, (char*)fStdout, (char*)fStderr);
-
- if (fResult) {
- #ifdef WIN_MAC
- fProcessNum= (long) MemNew(sizeof(ProcessSerialNumber));
- *((ProcessSerialNumberPtr) fProcessNum)= gChildProcessSN;
- #else
- fProcessNum= gChildProcessSN;
- #endif
-
- #ifdef WIN_MSWIN
- // can we assume no multiprocessing?? that child app is terminated by here??
- DBurialTask* buryMe = new DBurialTask( gChildProcessSN, this);
- PostTask( buryMe);
- #endif
-
- //gChildList->InsertLast( this); // done in constructor;
- // can we assume only one copy of this in list ??
- }
- }
- return fResult;
- }
-
-
- void DChildApp::FileAction(DChildFile* aFile)
- {
- switch (aFile->fAction) {
- case DChildFile::kOpenPict:
- case DChildFile::kOpenText:
- gApplication->OpenDocument( aFile);
- break;
- default:
- break;
- }
- }
-
- void DChildApp::Finished()
- {
- fLaunched--; // ?? or use this as counter?
- if (fFiles) {
- short i, n= fFiles->GetSize();
- for (i=0; i<n; i++) {
- DChildFile* aFile= (DChildFile*) fFiles->At(i);
- if (aFile->Exists() && aFile->LengthF()>0)
- FileAction( aFile);
- aFile->ClearStorage();
- }
- }
- }
-
-
-
- // class DExternalHandler : public DChildApp
-
- DExternalHandler::DExternalHandler( char* cmdlineOrDocname) :
- DChildApp( cmdlineOrDocname, NULL, false, NULL, false)
- {
- }
-
- Boolean DExternalHandler::Launch()
- {
- return DChildApp::Launch();
- }
-
- void DExternalHandler::Finished()
- {
- DChildApp::Finished();
- }
-
-
-
-
-
- // class DChildAppManager : public DObject
-
-
- //static
- DList* DChildAppManager::gChildList = NULL; // new DList(); << bad on SGI // of DChildApp
-
- DChildAppManager::DChildAppManager()
- {
- }
-
-
- //static
- short DChildAppManager::BuryDeadChildApp( long theEvent)
- {
- #ifdef WIN_MAC
- short err;
- long appErr;
- Size actualSize;
- ProcessSerialNumber appSN;
- DescType returnedType;
- AppleEvent* theAppleEvent;
-
- if (theEvent) {
- theAppleEvent = (AppleEvent*) theEvent;
-
- err= ::AEGetParamPtr( theAppleEvent, keyErrorNumber, typeLongInteger,
- &returnedType, &appErr, sizeof(appErr), &actualSize);
- if (appErr == 0) {
- err = AEGetParamPtr( theAppleEvent, keyProcessSerialNumber, typeProcessSerialNumber,
- &returnedType, &appSN, sizeof(appSN), &actualSize);
- Boolean match;
- DChildApp* child= NULL;
- short i, n= gChildList->GetSize();
- for (i=0, match= false; !match && i<n; i++) {
- child= (DChildApp*) gChildList->At(i);
- err= ::SameProcess( (ProcessSerialNumberPtr)child->fProcessNum, &appSN, &match);
- }
-
- if (match) {
- child->Finished();
- //gChildList->Delete(child); // done by child destructor
- if (!child->fReusable) delete child;
- }
- }
- }
- #endif
-
- #if defined(WIN_MOTIF) || defined(WIN_MSWIN)
- // use unix(?) signals
- Boolean match;
- DChildApp* child= NULL;
- short i, n= gChildList->GetSize();
- for (i=0, match= false; !match && i<n; i++) {
- child= (DChildApp*) gChildList->At(i);
- match= (child->fProcessNum == theEvent);
- }
- if (match) {
- child->Finished();
- //gChildList->Delete(child); // done by child destructor
- if (!child->fReusable) delete child;
- }
- #endif
- return 0;
- }
-
-
-
-
-
-