//************************************************************************************** // Filename: CShellExecutor.cp // Part of Contextual Menu Workshop by Abracode Inc. // http://free.abracode.com/cmworkshop/ // Copyright © 2002-2003 Abracode, Inc. All rights reserved. // // Description: she sells sea shells // this code is based on MiniShell.c example from Apple //************************************************************************************** // Revision History: // Friday, September 13, 2002 - Original //************************************************************************************** #include "CShellExecutor.h" //for debugging: #include "CFAbstractCMPlugin.h" #include "DebugSettings.h" CShellExecutor::CShellExecutor() : mSysBundle(NULL) { Initialize(); } CShellExecutor::~CShellExecutor() { if(mSysBundle != NULL) { ::CFRelease(mSysBundle); } } void CShellExecutor::Initialize() { if( mSysBundle != NULL ) return; //already initialized // Load the "System.framework" bundle. Most UNIX/BSD routines are in the System.framework OSStatus err = CShellExecutor::LoadFrameworkBundle( CFSTR("System.framework"), &mSysBundle ); if (err != noErr) return;//error situation - mSysBundle is set to NULL by LoadFrameworkBundle // Load the Mach-O function pointers for the routines we will be using. BSDfread = (BSDfreadFuncPtr) CFBundleGetFunctionPointerForName( mSysBundle, CFSTR("fread") ); BSDpopen = (BSDpopenFuncPtr) CFBundleGetFunctionPointerForName( mSysBundle, CFSTR("popen") ); BSDpclose = (BSDpcloseFuncPtr) CFBundleGetFunctionPointerForName( mSysBundle, CFSTR("pclose") ); if ( (BSDpopen == NULL) || (BSDpclose == NULL) || (BSDfread == NULL) ) { ::CFRelease(mSysBundle); mSysBundle = NULL; return;//error situation } //sucess situation } void CShellExecutor::Execute( CFStringRef inCommand ) { if(inCommand == NULL) return; #if _DEBUG_ Str255 pString; if( ::CFStringGetPascalString(inCommand, pString, sizeof(Str255), kCFStringEncodingMacRoman) ) { DEBUG_STR( pString ); } else { DEBUG_STR( "\pCShellExecutor:Execute CFStringGetPascalString failed" ); } #endif //_DEBUG_ CFIndex uniCount = ::CFStringGetLength(inCommand); CFIndex maxCount = ::CFStringGetMaximumSizeForEncoding( uniCount, kCFStringEncodingUTF8 ); Ptr theString = ::NewPtrClear(maxCount +1);//one more for 0-termination if(theString != NULL) { if( ::CFStringGetCString( inCommand, theString, maxCount +1, kCFStringEncodingUTF8) ) { Execute( theString ); } ::DisposePtr(theString); } } // This routine does the interesting stuff, specifically the routine popen() loaded into the BSDpopen function pointer // effectively does a fork() and execv(). void CShellExecutor::Execute( char *inCommand ) { if( (mSysBundle == NULL) || (inCommand == NULL) ) return;//not initialized or could not be initialized TRACE_STR( "\pCShellExecutor. Executing silently now" ); FILE *fp = BSDpopen( inCommand, "r" ); if ( fp != NULL ) { (void) BSDpclose( fp ); } } //static public OSStatus CShellExecutor::LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) { OSStatus err; FSRef frameworksFolderRef; CFURLRef baseURL; CFURLRef bundleURL; if ( bundlePtr == NULL ) return( -1 ); *bundlePtr = NULL; baseURL = NULL; bundleURL = NULL; err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef); if (err == noErr) { baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef); if (baseURL == NULL) { err = coreFoundationUnknownErr; } } if (err == noErr) { bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false); if (bundleURL == NULL) { err = coreFoundationUnknownErr; } } if (err == noErr) { *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL); if (*bundlePtr == NULL) { err = coreFoundationUnknownErr; } } if (err == noErr) { if ( ! CFBundleLoadExecutable( *bundlePtr ) ) { err = coreFoundationUnknownErr; } } // Clean up. if ( (err != noErr) && (*bundlePtr != NULL) ) { CFRelease(*bundlePtr); *bundlePtr = NULL; } if (bundleURL != NULL) { CFRelease(bundleURL); } if (baseURL != NULL) { CFRelease(baseURL); } return err; }