Пример #1
0
bool os_initialize( adobe::application_t* theApp )
{
    //
    // On the Mac we need to install the application menus, respond
    // to AppleEvents and set the resource path. We set the resource
    // path first.
    //
    ProcessSerialNumber psn;
    ADOBE_REQUIRE_STATUS( GetCurrentProcess( &psn ) );

    FSRef location;
    ADOBE_REQUIRE_STATUS( GetProcessBundleLocation( &psn, &location ) );

    theApp->set_resource_directory( fsref_to_path( location ) / "Contents" / "Resources" );

    //
    // Now load our bundle, sign up for AppleEvents and show the menu.
    //
    CFBundleRef bundle = CFBundleGetMainBundle();
    IBNibRef    nibs = 0;

    if( !bundle ) return false;

    ADOBE_REQUIRE_STATUS( CreateNibReferenceWithCFBundle( bundle, kMainNibFileName, &nibs ) );

    if( !nibs )
    {
        ::CFRelease( bundle );

        return false;
    }

    //
    // Sign up to handle the "Open" AppleEvent.
    //
    static adobe::auto_resource<AEEventHandlerUPP> ae_handler( NewAEEventHandlerUPP( handle_open ) );

    AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, ae_handler.get(), 0, false );

    //
    // Install the menu, and it's event handler.
    //
    ADOBE_REQUIRE_STATUS( SetMenuBarFromNib( nibs, kMenuBarNibName ) );

    static EventTypeSpec                            hi_event = { kEventClassCommand, kHICommandFromMenu };
    static adobe::auto_resource<EventHandlerUPP>    hi_handler( NewEventHandlerUPP( menu_command ) );

    InstallApplicationEventHandler( hi_handler.get(), 1, &hi_event, theApp, 0 );

    //
    // Register this app as an Appearance Client
    //
    // Apple docs: "This function does nothing on Mac OS X. Do not call it."
    //
    // RegisterAppearanceClient();

    return true;
}
Пример #2
0
CFURLRef copyCurrentProcessURL(void) {
	ProcessSerialNumber psn = { 0, kCurrentProcess };
	FSRef fsref;
	CFURLRef URL = NULL;
	OSStatus err = GetProcessBundleLocation(&psn, &fsref);
	if (err != noErr) {
		NSLog(CFSTR("in copyCurrentProcessURL in CFGrowlAdditions: Could not get application location, because GetProcessBundleLocation returned %li\n"), (long)err);
	} else {
		URL = CFURLCreateFromFSRef(kCFAllocatorDefault, &fsref);
	}
	return URL;
}
Пример #3
0
char *get_exename(char *buf, size_t size)
{
    ProcessSerialNumber PSN;
    FSRef ref;

    if (GetCurrentProcess(&PSN) < 0 ||
        GetProcessBundleLocation(&PSN, &ref) < 0 ||
        FSRefMakePath(&ref, buf, size) < 0)
        return NULL;

    return buf;
}
Пример #4
0
OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr) {
   OSErr err;
   ProcessSerialNumber psn;
   err = GetCurrentProcess(&psn);
   if (err != noErr) return err;

   FSRef location;
   err = GetProcessBundleLocation(&psn, &location);
   if (err != noErr) return err;

   return FSGetCatalogInfo(&location, kFSCatInfoNone, 
     NULL, NULL, theFSSpecPtr, NULL);
}
Пример #5
0
Plugger::Plugger() {
    char temp[256];

    _searchpath = NULL;

    addsearchdir(PACKAGE_LIB_DIR);

    sprintf(temp,"%s/.freej/plugins",getenv("HOME"));
    addsearchdir(temp);

    addsearchdir("/usr/lib/FreeFrame");
    addsearchdir("/usr/local/lib/FreeFrame");
#ifdef WITH_FREI0R
    addsearchdir("/usr/lib/frei0r-1");
    addsearchdir("/usr/lib64/frei0r-1");
    addsearchdir("/usr/local/lib/frei0r-1");
    addsearchdir("/opt/local/lib/frei0r-1");
#endif

//   addsearchdir("/usr/lib/freej");
//   addsearchdir("/usr/local/lib/freej");
//   addsearchdir("/opt/video/lib/freej");
#ifdef HAVE_DARWIN
    ProcessSerialNumber psn;
    GetProcessForPID(getpid(), &psn);
    FSRef location;
    GetProcessBundleLocation(&psn, &location);
    // 238 == 256 - strlen("/Contents/Plugins") - 1
    FSRefMakePath(&location, (UInt8 *)temp, 238);
    strcat(temp, "/Contents/Plugins");
    addsearchdir(temp);
    sprintf(temp, "%s/Library/Application Support/FreeJ", getenv("HOME"));
    addsearchdir(temp);
    sprintf(temp, "%s/Library/Application Support/FreeFrame", getenv("HOME"));
    addsearchdir(temp);
    addsearchdir("/Library/Application Support/FreeJ");
    addsearchdir("/Library/Application Support/FreeFrame");
#endif

}
Пример #6
0
OSStatus FindPIDForWoW(pid_t *pid) {
    CFURLRef outAppURL;
    OSErr err;
	err = LSFindApplicationForInfo(NULL,
								   (CFStringRef)@"com.blizzard.worldofwarcraft",
								   NULL,
								   NULL,
								   &outAppURL);
    err = 0;
	FSRef desired, found;
	ProcessSerialNumber psn = {0, kNoProcess};
    
	if (!CFURLGetFSRef(outAppURL, &desired)) return errFSBadFSRef;
	do {
		err = GetNextProcess(&psn);
		if (err) return err; // -600 = process not found
		err = GetProcessBundleLocation(&psn, &found);
	} while (err || FSCompareFSRefs(&desired, &found));
	err = GetProcessPID(&psn, pid);
	if (err) return err;
	return noErr;
}
Пример #7
0
//---------------------------------------------------------------------------------------------
int main()
{
    static const EventTypeSpec  sApplicationEvents[] = {{ kEventClassCommand, kEventCommandProcess }};
    OSErr err;
    
    if (!SystemVersionRequired(0x1020))
    {
	DialogRef theAlert;
	CreateStandardAlert(kAlertStopAlert, CFSTR("Need 10.2 or later!"), NULL, NULL, &theAlert);
	RunStandardAlert(theAlert, NULL, NULL);
	return 0;
    }
    
    ProcessSerialNumber psn = {0, kCurrentProcess};
    err = GetProcessBundleLocation(&psn, &gApplicationBundleFSRef);

    err = CreateNibReference(CFSTR("CarbonSketch"), &gOurNibRef );
    require_noerr( err, CantGetNibRef );

    err = SetMenuBarFromNib( gOurNibRef, CFSTR("MenuBar") );
    require_noerr( err, SetMenuBarFromNib_FAILED );

    AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, DoOpenApp, 0, false);
    AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, DoOpenDocuments, 0, false);
//  AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, DoPrintDocuments, 0, false);

    InstallApplicationEventHandler( NewEventHandlerUPP(AppEventHandlerProc), 
                                    GetEventTypeCount(sApplicationEvents), 
                                    sApplicationEvents, 0, NULL );

    RunApplicationEventLoop();

SetMenuBarFromNib_FAILED:
    DisposeNibReference(gOurNibRef);

CantGetNibRef:
    return err;
}
Пример #8
0
static PyObject *AE_PSNDescForApplicationPath(PyObject* self, PyObject* args)
{
	ProcessSerialNumber psn = {0, kNoProcess};
	FSRef appRef, foundRef;
	AEDesc result;
	OSStatus err;
	
	if (!PyArg_ParseTuple(args, "O&", 
								AE_GetFSRef, &appRef))
		return NULL;
	while (1) {
		err = GetNextProcess(&psn);
		if (err) return AE_MacOSError(err);
		err = GetProcessBundleLocation(&psn, &foundRef);
		if (err == noErr && FSCompareFSRefs(&appRef, &foundRef) == noErr) break;
	}
	err = AECreateDesc(typeProcessSerialNumber,
	                   &psn, sizeof(psn),
	                   &result);
	if (err != noErr) return AE_MacOSError(err);
	return Py_BuildValue("O&",
	                     AE_AEDesc_New, &result);
}
Пример #9
0
// Initialise PhysicsFS, set up basic search paths and add arguments from .ini file.
// The .ini file can be in either the user directory or the same directory as the program.
// The user directory is searched first.
void PHYSFSX_init(int argc, char *argv[])
{
#if defined(__unix__)
	const char *path = NULL;
#endif
#ifdef macintosh	// Mac OS 9
	char base_dir[PATH_MAX];
	int bundle = 0;
#else
#define base_dir PHYSFS_getBaseDir()
#endif
	
	PHYSFS_init(argv[0]);
	atexit(PHYSFSX_deinit);
	PHYSFS_permitSymbolicLinks(1);
	
#ifdef macintosh
	strcpy(base_dir, PHYSFS_getBaseDir());
	if (strstr(base_dir, ".app:Contents:MacOSClassic"))	// the Mac OS 9 program is still in the .app bundle
	{
		char *p;
		
		bundle = 1;
		if (base_dir[strlen(base_dir) - 1] == ':')
			base_dir[strlen(base_dir) - 1] = '\0';
		p = strrchr(base_dir, ':'); *p = '\0';	// path to 'Contents'
		p = strrchr(base_dir, ':'); *p = '\0';	// path to bundle
		p = strrchr(base_dir, ':'); *p = '\0';	// path to directory containing bundle
	}
#endif
	
#if (defined(__APPLE__) && defined(__MACH__))	// others?
	chdir(base_dir);	// make sure relative hogdir paths work
#endif
	
#if defined(__unix__)
	char fullPath[PATH_MAX + 5];
# if !(defined(__APPLE__) && defined(__MACH__))
	path = "~/.d2x-rebirth/";
# else
	path = "~/Library/Preferences/D2X Rebirth/";
# endif
	
	if (path[0] == '~') // yes, this tilde can be put before non-unix paths.
	{
		const char *home = PHYSFS_getUserDir();
		
		strcpy(fullPath, home); // prepend home to the path
		path++;
		if (*path == *PHYSFS_getDirSeparator())
			path++;
		strncat(fullPath, path, PATH_MAX + 5 - strlen(home));
	}
	else
		strncpy(fullPath, path, PATH_MAX + 5);
	
	PHYSFS_setWriteDir(fullPath);
	if (!PHYSFS_getWriteDir())
	{                                               // need to make it
		char *p;
		char ancestor[PATH_MAX + 5];    // the directory which actually exists
		char child[PATH_MAX + 5];               // the directory relative to the above we're trying to make
		
		strcpy(ancestor, fullPath);
		while (!PHYSFS_getWriteDir() && ((p = strrchr(ancestor, *PHYSFS_getDirSeparator()))))
		{
			if (p[1] == 0)
			{                                       // separator at the end (intended here, for safety)
				*p = 0;                 // kill this separator
				if (!((p = strrchr(ancestor, *PHYSFS_getDirSeparator()))))
					break;          // give up, this is (usually) the root directory
			}
			
			p[1] = 0;                       // go to parent
			PHYSFS_setWriteDir(ancestor);
		}
		
		strcpy(child, fullPath + strlen(ancestor));
		for (p = child; (p = strchr(p, *PHYSFS_getDirSeparator())); p++)
			*p = '/';
		PHYSFS_mkdir(child);
		PHYSFS_setWriteDir(fullPath);
	}
	
	PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 1);
#endif
	
	PHYSFS_addToSearchPath(base_dir, 1);
	InitArgs( argc,argv );
	PHYSFS_removeFromSearchPath(base_dir);
	
	if (!PHYSFS_getWriteDir())
	{
		PHYSFS_setWriteDir(base_dir);
		if (!PHYSFS_getWriteDir())
			Error("can't set write dir: %s\n", PHYSFS_getLastError());
		else
			PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 0);
	}
	
	//tell PHYSFS where hogdir is
	if (GameArg.SysHogDir)
		PHYSFS_addToSearchPath(GameArg.SysHogDir,1);
#if defined(__unix__)
	else if (!GameArg.SysNoHogDir)
		PHYSFS_addToSearchPath(SHAREPATH, 1);
#endif
	
	PHYSFSX_addRelToSearchPath("data", 1);	// 'Data' subdirectory
	
	// For Macintosh, add the 'Resources' directory in the .app bundle to the searchpaths
#if defined(__APPLE__) && defined(__MACH__)
	{
		ProcessSerialNumber psn = { 0, kCurrentProcess };
		FSRef fsref;
		OSStatus err;
		
		err = GetProcessBundleLocation(&psn, &fsref);
		if (err == noErr)
			err = FSRefMakePath(&fsref, (ubyte *)fullPath, PATH_MAX);
		
		if (err == noErr)
		{
			strncat(fullPath, "/Contents/Resources/", PATH_MAX + 4 - strlen(fullPath));
			fullPath[PATH_MAX + 4] = '\0';
			PHYSFS_addToSearchPath(fullPath, 1);
		}
	}
#elif defined(macintosh)
	if (bundle)
	{
		base_dir[strlen(base_dir)] = ':';	// go back in the bundle
		base_dir[strlen(base_dir)] = ':';	// go back in 'Contents'
		strncat(base_dir, ":Resources:", PATH_MAX - 1 - strlen(base_dir));
		base_dir[PATH_MAX - 1] = '\0';
		PHYSFS_addToSearchPath(base_dir, 1);
	}
#endif
}
Пример #10
0
void *updatethreadproc(void*)
{
	char tempDir[PATH_MAX] = "";		/* Flawfinder: ignore */
	FSRef tempDirRef;
	char temp[PATH_MAX] = "";	/* Flawfinder: ignore */
	// *NOTE: This buffer length is used in a scanf() below.
	char deviceNode[1024] = "";	/* Flawfinder: ignore */
	LLFILE *downloadFile = NULL;
	OSStatus err;
	ProcessSerialNumber psn;
	char target[PATH_MAX] = "";		/* Flawfinder: ignore */
	FSRef targetRef;
	FSRef targetParentRef;
	FSVolumeRefNum targetVol;
	FSRef trashFolderRef;
	Boolean replacingTarget = false;

	memset(&tempDirRef, 0, sizeof(tempDirRef));
	memset(&targetRef, 0, sizeof(targetRef));
	memset(&targetParentRef, 0, sizeof(targetParentRef));
	
	try
	{
		// Attempt to get a reference to the Second Life application bundle containing this updater.
		// Any failures during this process will cause us to default to updating /Applications/Second Life.app
		{
			FSRef myBundle;

			err = GetCurrentProcess(&psn);
			if(err == noErr)
			{
				err = GetProcessBundleLocation(&psn, &myBundle);
			}

			if(err == noErr)
			{
				// Sanity check:  Make sure the name of the item referenced by targetRef is "Second Life.app".
				FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target));
				
				llinfos << "Updater bundle location: " << target << llendl;
			}
			
			// Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app
			// so we need to go up 3 levels to get the path to the main application bundle.
			if(err == noErr)
			{
				err = FSGetCatalogInfo(&myBundle, kFSCatInfoNone, NULL, NULL, NULL, &targetRef);
			}
			if(err == noErr)
			{
				err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef);
			}
			if(err == noErr)
			{
				err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef);
			}
			
			// And once more to get the parent of the target
			if(err == noErr)
			{
				err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetParentRef);
			}
			
			if(err == noErr)
			{
				FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target));
				llinfos << "Path to target: " << target << llendl;
			}
			
			// Sanity check: make sure the target is a bundle with the right identifier
			if(err == noErr)
			{
				// Assume the worst...
				err = -1;

				if(isFSRefViewerBundle(&targetRef))
				{
					// This is the bundle we're looking for.
					err = noErr;
					replacingTarget = true;
				}
			}
			
			// Make sure the target's parent directory is writable.
			if(err == noErr)
			{
				if(!isDirWritable(targetParentRef))
				{
					// Parent directory isn't writable.
					llinfos << "Target parent directory not writable." << llendl;
					err = -1;
					replacingTarget = false;
				}
			}

			if(err != noErr)
			{
				Boolean isDirectory;
				llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl;
				
				// Set up the parent directory
				err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory);
				if((err != noErr) || (!isDirectory))
				{
					// We're so hosed.
					llinfos << "Applications directory not found, giving up." << llendl;
					throw 0;
				}
				
				snprintf(target, sizeof(target), "/Applications/%s.app", gProductName);		

				memset(&targetRef, 0, sizeof(targetRef));
				err = FSPathMakeRef((UInt8*)target, &targetRef, NULL);
				if(err == fnfErr)
				{
					// This is fine, just means we're not replacing anything.
					err = noErr;
					replacingTarget = false;
				}
				else
				{
					replacingTarget = true;
				}

				// Make sure the target's parent directory is writable.
				if(err == noErr)
				{
					if(!isDirWritable(targetParentRef))
					{
						// Parent directory isn't writable.
						llinfos << "Target parent directory not writable." << llendl;
						err = -1;
						replacingTarget = false;
					}
				}

			}
			
			// If we haven't fixed all problems by this point, just bail.
			if(err != noErr)
			{
				llinfos << "Unable to pick a target, giving up." << llendl;
				throw 0;
			}
		}
		
		// Find the volID of the volume the target resides on
		{
			FSCatalogInfo info;
			err = FSGetCatalogInfo(
				&targetParentRef,
				kFSCatInfoVolume,
				&info,
				NULL, 
				NULL,  
				NULL);
				
			if(err != noErr)
				throw 0;
			
			targetVol = info.volume;
		}

		// Find the temporary items and trash folders on that volume.
		err = FSFindFolder(
			targetVol,
			kTrashFolderType,
			true,
			&trashFolderRef);

		if(err != noErr)
			throw 0;

#if 0 // *HACK for DEV-11935 see below for details.

		FSRef tempFolderRef;

		err = FSFindFolder(
			targetVol,
			kTemporaryFolderType,
			true,
			&tempFolderRef);
		
		if(err != noErr)
			throw 0;
		
		err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp));

		if(err != noErr)
			throw 0;

#else		

		// *HACK for DEV-11935  the above kTemporaryFolderType query was giving
		// back results with path names that seem to be too long to be used as
		// mount points.  I suspect this incompatibility was introduced in the
		// Leopard 10.5.2 update, but I have not verified this. 
		char const HARDCODED_TMP[] = "/tmp";
		strncpy(temp, HARDCODED_TMP, sizeof(HARDCODED_TMP));

#endif // 0 *HACK for DEV-11935
		
		// Skip downloading the file if the dmg was passed on the command line.
		std::string dmgName;
		if(gDmgFile != NULL) {
			dmgName = basename((char *)gDmgFile);
			char * dmgDir = dirname((char *)gDmgFile);
			strncpy(tempDir, dmgDir, sizeof(tempDir));
			err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);
			if(err != noErr) throw 0;
			chdir(tempDir);
			goto begin_install;
		} else {
			// Continue on to download file.
			dmgName = "SecondLife.dmg";
		}

		
		strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1);
		if(mkdtemp(temp) == NULL)
		{
			throw 0;
		}
		
		strncpy(tempDir, temp, sizeof(tempDir));
		temp[sizeof(tempDir) - 1] = '\0';
		
		llinfos << "tempDir is " << tempDir << llendl;

		err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);

		if(err != noErr)
			throw 0;
				
		chdir(tempDir);
		
		snprintf(temp, sizeof(temp), "SecondLife.dmg");		
		
		downloadFile = LLFile::fopen(temp, "wb");		/* Flawfinder: ignore */
		if(downloadFile == NULL)
		{
			throw 0;
		}

		{
			CURL *curl = curl_easy_init();

			curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
	//		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback);
			curl_easy_setopt(curl, CURLOPT_FILE, downloadFile);
			curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
			curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func);
			curl_easy_setopt(curl, CURLOPT_URL,	gUpdateURL);
			curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
			
			sendProgress(0, 1, CFSTR("Downloading..."));
			
			CURLcode result = curl_easy_perform(curl);
			
			curl_easy_cleanup(curl);
			
			if(gCancelled)
			{
				llinfos << "User cancel, bailing out."<< llendl;
				throw 0;
			}
			
			if(result != CURLE_OK)
			{
				llinfos << "Error " << result << " while downloading disk image."<< llendl;
				throw 0;
			}
			
			fclose(downloadFile);
			downloadFile = NULL;
		}

	begin_install:
		sendProgress(0, 0, CFSTR("Mounting image..."));
		LLFile::mkdir("mnt", 0700);
		
		// NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder,
		//		but if our cleanup fails, this makes it much harder for the user to unmount the image.
		std::string mountOutput;
		boost::format cmdFormat("hdiutil attach %s -mountpoint mnt");
		cmdFormat % dmgName;
		FILE* mounter = popen(cmdFormat.str().c_str(), "r");		/* Flawfinder: ignore */
		
		if(mounter == NULL)
		{
			llinfos << "Failed to mount disk image, exiting."<< llendl;
			throw 0;
		}
		
		// We need to scan the output from hdiutil to find the device node it uses to attach the disk image.
		// If we don't have this information, we can't detach it later.
		while(mounter != NULL)
		{
			size_t len = fread(temp, 1, sizeof(temp)-1, mounter);
			temp[len] = 0;
			mountOutput.append(temp);
			if(len < sizeof(temp)-1)
			{
				// End of file or error.
				int result = pclose(mounter);
				if(result != 0)
				{
					// NOTE: We used to abort here, but pclose() started returning 
					// -1, possibly when the size of the DMG passed a certain point 
					llinfos << "Unexpected result closing pipe: " << result << llendl; 
				}
				mounter = NULL;
			}
		}
		
		if(!mountOutput.empty())
		{
			const char *s = mountOutput.c_str();
			const char *prefix = "/dev/";
			char *sub = strstr(s, prefix);
			
			if(sub != NULL)
			{
				sub += strlen(prefix);	/* Flawfinder: ignore */
				sscanf(sub, "%1023s", deviceNode);	/* Flawfinder: ignore */
			}
		}
		
		if(deviceNode[0] != 0)
		{
			llinfos << "Disk image attached on /dev/" << deviceNode << llendl;
		}
		else
		{
			llinfos << "Disk image device node not found!" << llendl;
			throw 0; 
		}
		
		// Get an FSRef to the new application on the disk image
		FSRef sourceRef;
		FSRef mountRef;
		snprintf(temp, sizeof(temp), "%s/mnt", tempDir);		

		llinfos << "Disk image mount point is: " << temp << llendl;

		err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL);
		if(err != noErr)
		{
			llinfos << "Couldn't make FSRef to disk image mount point." << llendl;
			throw 0;
		}

		sendProgress(0, 0, CFSTR("Searching for the app bundle..."));
		err = findAppBundleOnDiskImage(&mountRef, &sourceRef);
		if(err != noErr)
		{
			llinfos << "Couldn't find application bundle on mounted disk image." << llendl;
			throw 0;
		}
		else
		{
			llinfos << "found the bundle." << llendl;
		}

		sendProgress(0, 0, CFSTR("Preparing to copy files..."));
		
		FSRef asideRef;
		char aside[MAX_PATH];		/* Flawfinder: ignore */
		
		// this will hold the name of the destination target
		CFStringRef appNameRef;

		if(replacingTarget)
		{
			// Get the name of the target we're replacing
			HFSUniStr255 appNameUniStr;
			err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL);
			if(err != noErr)
				throw 0;
			appNameRef = FSCreateStringFromHFSUniStr(NULL, &appNameUniStr);
			
			// Move aside old version (into work directory)
			err = FSMoveObject(&targetRef, &tempDirRef, &asideRef);
			if(err != noErr)
			{
				llwarns << "failed to move aside old version (error code " << 
					err << ")" << llendl;
				throw 0;
			}

			// Grab the path for later use.
			err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside));
		}
		else
		{
			// Construct the name of the target based on the product name
			char appName[MAX_PATH];		/* Flawfinder: ignore */
			snprintf(appName, sizeof(appName), "%s.app", gProductName);		
			appNameRef = CFStringCreateWithCString(NULL, appName, kCFStringEncodingUTF8);
		}
		
		sendProgress(0, 0, CFSTR("Copying files..."));
		
		llinfos << "Starting copy..." << llendl;

		// Copy the new version from the disk image to the target location.
		err = FSCopyObjectSync(
				&sourceRef,
				&targetParentRef,
				appNameRef,
				&targetRef,
				kFSFileOperationDefaultOptions);
		
		// Grab the path for later use.
		err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target));
		if(err != noErr)
			throw 0;

		llinfos << "Copy complete. Target = " << target << llendl;

		if(err != noErr)
		{
			// Something went wrong during the copy.  Attempt to put the old version back and bail.
			(void)FSDeleteObject(&targetRef);
			if(replacingTarget)
			{
				(void)FSMoveObject(&asideRef, &targetParentRef, NULL);
			}
			throw 0;
		}
		else
		{
			// The update has succeeded.  Clear the cache directory.

			sendProgress(0, 0, CFSTR("Clearing cache..."));
	
			llinfos << "Clearing cache..." << llendl;
			
			char mask[LL_MAX_PATH];		/* Flawfinder: ignore */
			snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str());		
			gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
			
			llinfos << "Clear complete." << llendl;

		}
	}
	catch(...)
	{
		if(!gCancelled)
			if(gFailure == noErr)
				gFailure = -1;
	}

	// Failures from here on out are all non-fatal and not reported.
	sendProgress(0, 3, CFSTR("Cleaning up..."));

	// Close disk image file if necessary
	if(downloadFile != NULL)
	{
		llinfos << "Closing download file." << llendl;

		fclose(downloadFile);
		downloadFile = NULL;
	}

	sendProgress(1, 3);
	// Unmount image
	if(deviceNode[0] != 0)
	{
		llinfos << "Detaching disk image." << llendl;

		snprintf(temp, sizeof(temp), "hdiutil detach '%s'", deviceNode);		
		system(temp);		/* Flawfinder: ignore */
	}

	sendProgress(2, 3);

	// Move work directory to the trash
	if(tempDir[0] != 0)
	{
//		chdir("/");
//		FSDeleteObjects(tempDirRef);

		llinfos << "Moving work directory to the trash." << llendl;

		err = FSMoveObject(&tempDirRef, &trashFolderRef, NULL);
		if(err != noErr) {
			llwarns << "failed to move files to trash, (error code " <<
				err << ")" << llendl;
		}

//		snprintf(temp, sizeof(temp), "rm -rf '%s'", tempDir);
//		printf("%s\n", temp);
//		system(temp);
	}
	
	if(!gCancelled  && !gFailure && (target[0] != 0))
	{
		llinfos << "Touching application bundle." << llendl;

		snprintf(temp, sizeof(temp), "touch '%s'", target);		
		system(temp);		/* Flawfinder: ignore */

		llinfos << "Launching updated application." << llendl;

		snprintf(temp, sizeof(temp), "open '%s'", target);		
		system(temp);		/* Flawfinder: ignore */
	}

	sendDone();
	
	return(NULL);
}
Пример #11
0
bool CBOINCClientManager::StartupBOINCCore() {
    wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::StartupBOINCCore - Function Begin"));

    bool                bReturnValue = false;
    wxString            strExecute = wxEmptyString;

    if (IsBOINCCoreRunning()) return true;

#if   defined(__WXMSW__)
    LPTSTR  szExecute = NULL;
    LPTSTR  szDataDirectory = NULL;

    if (IsBOINCConfiguredAsDaemon()) {
        return (!!StartBOINCService());
    }

    // Append synecd.exe to the end of the strExecute string
    strExecute.Printf(
        wxT("\"%ssynecd.exe\" --redirectio --launched_by_manager %s"),
        wxGetApp().GetRootDirectory().c_str(),
        wxGetApp().GetArguments().c_str()
    );

    PROCESS_INFORMATION pi;
    STARTUPINFO         si;
    BOOL                bProcessStarted;

    memset(&pi, 0, sizeof(pi));
    memset(&si, 0, sizeof(si));

    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;

    szExecute = (LPTSTR)strExecute.c_str();
    if (wxGetApp().GetDataDirectory().empty()) {
        szDataDirectory = NULL;
    } else {
        szDataDirectory = (LPTSTR)wxGetApp().GetDataDirectory().c_str();
    }

    wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szExecute '%s'\n"), szExecute);
    wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szDataDirectory '%s'\n"), szDataDirectory);

    bProcessStarted = CreateProcess(
        NULL,
        szExecute,
        NULL,
        NULL,
        FALSE,
        CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW,
        NULL,
        szDataDirectory,
        &si,
        &pi
    );
    if (bProcessStarted) {
        m_lBOINCCoreProcessId = pi.dwProcessId;
        m_hBOINCCoreProcess = pi.hProcess;
    }

#elif defined(__WXMAC__)

    char buf[1024];
    char *argv[5];
    ProcessSerialNumber ourPSN;
    FSRef ourFSRef;
    OSErr err;

    if (IsBOINCConfiguredAsDaemon() == NewStyleDaemon) {
        system ("launchctl load /Library/LaunchDaemons/com.googlecode.synecdoche.plist");
        system ("launchctl start com.googleccode.synecdoche");
        bReturnValue = IsBOINCCoreRunning();
    } else {
        
        // Get the full path to core client inside this application's bundle
        err = GetCurrentProcess (&ourPSN);
        if (err == noErr) {
            err = GetProcessBundleLocation(&ourPSN, &ourFSRef);
        }
        if (err == noErr) {
            err = FSRefMakePath (&ourFSRef, (UInt8*)buf, sizeof(buf));
        }
        if (err == noErr) {
#if 0   // The Mac version of wxExecute(wxString& ...) crashes if there is a space in the path
            strExecute = wxT("\"");            
            strExecute += wxT(buf);
            strExecute += wxT("/Contents/Resources/synecd\" --redirectio --launched_by_manager");
            m_lBOINCCoreProcessId = ::wxExecute(strExecute);
#else   // Use wxExecute(wxChar **argv ...) instead of wxExecute(wxString& ...)
            strcat(buf, "/Contents/Resources/synecd");
            argv[0] = buf;
            argv[1] = "--redirectio";
            argv[2] = "--launched_by_manager";
            argv[3] = NULL;
#ifdef SANDBOX
            if (!g_use_sandbox) {
                argv[3] = "--insecure";
                argv[4] = NULL;
            }
#endif
            // Under wxMac-2.8.0, wxExecute starts a separate thread
            // to wait for child's termination.
            // That wxProcessTerminationThread uses a huge amount of processor
            // time (about 11% of one CPU on 2GHz Intel Dual-Core Mac).
//                m_lBOINCCoreProcessId = ::wxExecute(argv);
            run_program(
                "/Library/Application Support/Synecdoche Data",
                buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId
            );
#endif
        } else {
            buf[0] = '\0';
        }
    }

#else   // Unix based systems

    // Append boinc.exe to the end of the strExecute string and get ready to rock
    strExecute = ::wxGetCwd() + wxT("/boinc --redirectio --launched_by_manager");
#ifdef SANDBOX
    if (!g_use_sandbox) {
        strExecute += wxT(" --insecure");
    }
#endif // SANDBOX

    wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szExecute '%s'\n"), strExecute.c_str());
    wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szDataDirectory '%s'\n"), ::wxGetCwd().c_str());

    m_lBOINCCoreProcessId = ::wxExecute(strExecute);
    
#endif

    if (0 != m_lBOINCCoreProcessId) {
        m_bBOINCStartedByManager = true;
        bReturnValue = true;
        // Allow time for daemon to start up so we don't keep relaunching it
        for (int i = 0; i < 100; ++i) { // Wait up to 4 seconds in 40ms increments
            if (IsBOINCCoreRunning()) {
                break;
            }
            boinc_sleep(0.04);
        }
    }

    wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::StartupBOINCCore - Function End"));
    return bReturnValue;
}
Пример #12
0
static PyObject *AE_AddressDescToPath(PyObject *_self, PyObject *_args)
{
	AEDesc desc;
	ProcessSerialNumber psn;
	pid_t pid;
	OSType creatorType = kLSUnknownCreator;
	Size cSize;
	char *cStr;
	CFStringRef bundleID = NULL;
	FSRef fsref;
	UInt8 path[PATH_MAX];
	PyObject* pathObj;
	OSStatus err;
	
	if (!PyArg_ParseTuple(_args, "O&",
						  AE_AEDesc_Convert, &desc))
	return NULL;
	
	switch (desc.descriptorType) {
	
		case typeKernelProcessID:
			err = AEGetDescData(&desc, &pid, sizeof(pid));
			if (err) return AE_MacOSError(err);
			err = GetProcessForPID(pid, &psn);
			if (err) return AE_MacOSError(err);
			err = GetProcessBundleLocation(&psn, &fsref);
			if (err) return AE_MacOSError(err);
			break;
		
		case typeProcessSerialNumber:
			err = AEGetDescData(&desc, &psn, sizeof(psn));
			if (err) return AE_MacOSError(err);
			err = GetProcessBundleLocation(&psn, &fsref);
			if (err) return AE_MacOSError(err);
			break;
		
		case typeApplSignature:
			err = AEGetDescData(&desc, &creatorType, sizeof(creatorType));
			if (err) return AE_MacOSError(err);
			err = LSFindApplicationForInfo(creatorType, bundleID, NULL, &fsref, NULL);
			if (err) return AE_MacOSError(err);
			break;
		
		case typeApplicationBundleID:
			cSize = AEGetDescDataSize(&desc);
			cStr = malloc((size_t)cSize);
			if (!cStr) return AE_MacOSError(errAECoercionFail);
			err = AEGetDescData(&desc, cStr, cSize);
			if (err) return AE_MacOSError(err);
			bundleID = CFStringCreateWithBytes(NULL, (UInt8 *)cStr, (CFIndex)cSize, kCFStringEncodingUTF8, 0);
			free(cStr);
			if (!bundleID) return AE_MacOSError(errAECoercionFail);
			err = LSFindApplicationForInfo(creatorType, bundleID, NULL, &fsref, NULL);
			if (err) return AE_MacOSError(err);
			break;
		
		case typeMachPort: // unsupported
		case typeApplicationURL: // unsupported (remote applications)
		default: 
			return AE_MacOSError(errAECoercionFail);
	}

	err = FSRefMakePath(&fsref, path, sizeof(path));
	if (err) return AE_MacOSError(err);
	pathObj = PyUnicode_DecodeUTF8((char *)path, strlen((char *)path), NULL);
	return Py_BuildValue("O", pathObj);
}
Пример #13
0
// Returns FALSE (0) if owners and permissions are OK, else TRUE (1)
int check_security(
#ifdef _MAC_INSTALLER
char *bundlePath, char *dataPath,
#endif
int use_sandbox, int isManager, char* path_to_error, int len
) {
    passwd              *pw;
    group               *grp;
    gid_t               egid;
    uid_t               euid;
    char                dir_path[MAXPATHLEN], full_path[MAXPATHLEN];
    struct stat         sbuf;
    int                 retval;
    int                 useFakeProjectUserAndGroup = 0;
#ifdef __WXMAC__                            // If Mac BOINC Manager
    ProcessSerialNumber ourPSN;
    ProcessInfoRec      pInfo;
    FSRef               ourFSRef;
#endif

#define NUMBRANDS 3

char *saverName[NUMBRANDS];

saverName[0] = "BOINCSaver";
saverName[1] = "GridRepublic";
saverName[2] = "Progress Thru Processors";

    useFakeProjectUserAndGroup = ! use_sandbox;
#ifdef _DEBUG
#ifdef DEBUG_WITH_FAKE_PROJECT_USER_AND_GROUP
        useFakeProjectUserAndGroup = 1;
#endif
#endif      // _DEBUG

// GDB can't attach to applications which are running as a diferent user or group so
//  it ignores the S_ISUID and S_ISGID permisison bits when launching an application.
// To work around this, and to allow testing the uninstalled Deployment version, we
//  assume that the BOINC Client has the correct user and group. 
// We must get the BOINC Client's user and group differently depending on whether we
//  were called from the Manager or from the Client

#ifdef __WXMAC__                            // If Mac BOINC Manager
    // Get the full path to BOINC Manager application's bundle
    retval = GetCurrentProcess (&ourPSN);
    if (retval)
        return -1000;          // Should never happen

    memset(&pInfo, 0, sizeof(pInfo));
    pInfo.processInfoLength = sizeof( ProcessInfoRec );
    retval = GetProcessInformation(&ourPSN, &pInfo);
    if (retval)
        return -1001;          // Should never happen

    retval = GetProcessBundleLocation(&ourPSN, &ourFSRef);
    if (retval)
        return -1002;          // Should never happen

    retval = FSRefMakePath (&ourFSRef, (UInt8*)dir_path, sizeof(dir_path));
    if (retval)
        return -1003;          // Should never happen
#elif defined (_MAC_INSTALLER)
    strlcpy(dir_path, bundlePath, sizeof(dir_path));
#endif

    if (use_sandbox) {
#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If called from Mac BOINC Manager or installer
        // Get the full path to BOINC Client inside this application's bundle
        snprintf(full_path, sizeof(full_path),
            "%s/Contents/Resources/boinc", dir_path
        );
#else
    if (isManager) {             // If called from BOINC Manager but not on Mac
        getcwd(full_path, sizeof(full_path));
        // Assume Client is in current directory
        strlcat(full_path, "/boinc", sizeof(full_path));
    } else
        // If called from BOINC Client
        GetPathToThisProcess(full_path, sizeof(full_path));
#endif

        retval = stat(full_path, &sbuf);
        if (retval)
            return -1004;          // Should never happen

        if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != (S_ISUID | S_ISGID))
            return -1005;

        boinc_master_uid = sbuf.st_uid;
        boinc_master_gid = sbuf.st_gid;

#ifdef __WXMAC__
    if (!IsUserInGroupBM())
        return -1099;
#endif
    } else {
        boinc_master_uid = geteuid();
        boinc_master_gid = getegid();
    }

#ifdef _MAC_INSTALLER
   // Require absolute owner and group boinc_master:boinc_master
    strlcpy(boinc_master_user_name, REAL_BOINC_MASTER_NAME, sizeof(boinc_master_user_name));
    pw = getpwnam(boinc_master_user_name);
    if (pw == NULL)
        return -1006;      // User boinc_master does not exist
    boinc_master_uid = pw->pw_uid;

    strlcpy(boinc_master_group_name, REAL_BOINC_MASTER_NAME, sizeof(boinc_master_group_name));
    grp = getgrnam(boinc_master_group_name);
    if (grp == NULL)
        return -1007;                // Group boinc_master does not exist
    boinc_master_gid = grp->gr_gid;

#else   // Use current user and group (see comment above)

    pw = getpwuid(boinc_master_uid);
    if (pw == NULL)
        return -1008;      // Should never happen
    strlcpy(boinc_master_user_name, pw->pw_name, sizeof(boinc_master_user_name));

    grp = getgrgid(boinc_master_gid);
    if (grp == NULL)
        return -1009;
    strlcpy(boinc_master_group_name, grp->gr_name, sizeof(boinc_master_group_name));

#endif

    if (useFakeProjectUserAndGroup) {
        // For easier debugging of project applications
        strlcpy(boinc_project_user_name, boinc_master_user_name, sizeof(boinc_project_user_name));
        strlcpy(boinc_project_group_name, boinc_master_group_name, sizeof(boinc_project_group_name));
        boinc_project_uid = boinc_master_uid;
        boinc_project_gid = boinc_master_gid;
    } else {
        strlcpy(boinc_project_user_name, REAL_BOINC_PROJECT_NAME, sizeof(boinc_project_user_name));
        pw = getpwnam(boinc_project_user_name);
        if (pw == NULL)
            return -1010;      // User boinc_project does not exist
        boinc_project_uid = pw->pw_uid;

        strlcpy(boinc_project_group_name, REAL_BOINC_PROJECT_NAME, sizeof(boinc_project_group_name));
        grp = getgrnam(boinc_project_group_name);
        if (grp == NULL)
            return -1011;                // Group boinc_project does not exist
        boinc_project_gid = grp->gr_gid;
    }

#if 0   // Manager is no longer setgid
#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If Mac BOINC Manager or installer
        // Get the full path to BOINC Manager executable
        // inside this application's bundle
        //
        snprintf(full_path, sizeof(full_path), "%s/Contents/MacOS/", dir_path);

        // To allow for branding, assume name of executable inside bundle
        // is same as name of bundle
        //
        p = strrchr(dir_path, '/');         // Assume name of executable inside bundle is same as name of bundle
        if (p == NULL)
            p = dir_path - 1;
        strlcat(full_path, p+1, sizeof(full_path));
        p = strrchr(full_path, '.');         // Strip off  bundle extension (".app")
        if (p)
            *p = '\0'; 

        retval = lstat(full_path, &sbuf);
        if (retval)
            return -1013;          // Should never happen
        
        if (sbuf.st_gid != boinc_master_gid)
            return -1014;

        if (use_sandbox) {
            if ((sbuf.st_mode & S_ISGID) != S_ISGID)
                return -1015;
        }
#endif
#endif   // Manager is no longer setgid


#ifdef _MAC_INSTALLER
        // Require absolute owner and group boinc_master:boinc_master
        // Get the full path to BOINC Client inside this application's bundle
        //
        snprintf(full_path, sizeof(full_path),
            "%s/Contents/Resources/boinc", dir_path
        );

        retval = stat(full_path, &sbuf);
        if (retval)
            return -1016;          // Should never happen
        
        if (sbuf.st_gid != boinc_master_gid)
            return -1017;

        if (sbuf.st_uid != boinc_master_uid)
            return -1018;
#endif

#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If Mac BOINC Manager or installer
        // Version 6 screensaver has its own embedded switcher application, but older versions don't.
        // We don't allow unauthorized users to run the standard switcher application in the BOINC 
        // Data directory because they could use it to run as user & group boinc_project and damage 
        // project files.  The screensaver's gfx_switcher application has very limited functionality 
        // to avoid this risk.

        if (use_sandbox) {
            for (int i=0; i<NUMBRANDS; i++) {
                // Does gfx_switcher exist in screensaver bundle?
                sprintf(full_path, "/Library/Screen Savers/%s.saver/Contents/Resources/gfx_switcher", saverName[i]);
                retval = stat(full_path, &sbuf);
                if (! retval) {
#ifdef _DEBUG
                    if (sbuf.st_uid != boinc_master_uid)
                        return -1101;

                    if (sbuf.st_gid != boinc_master_gid)
                        return -1102;

                    if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != 0)
                        return -1103;
#else
                    if (sbuf.st_uid != 0)
                        return -1101;

                    if (sbuf.st_gid != boinc_master_gid)
                        return -1102;

                    if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != S_ISUID)
                        return -1103;
#endif
                }
            }
        }
#endif


//    rgid = getgid();
//    ruid = getuid();
    egid = getegid();
    euid = geteuid();

#ifdef _MAC_INSTALLER
    strlcpy(dir_path, dataPath, sizeof(dir_path));  // Installer
#else       // _MAC_INSTALLER
    getcwd(dir_path, sizeof(dir_path));             // Client or Manager

    if (! isManager) {                                   // If BOINC Client
    if (egid != boinc_master_gid)
            return -1019;     // Client should be running setgid boinc_master

        if (euid != boinc_master_uid)
            return -1020;     // BOINC Client should be running setuid boinc_master
    }
#endif

    retval = stat(dir_path, &sbuf);
    if (retval)
        return -1021;          // Should never happen

    if (use_sandbox) {

        // The top-level BOINC Data directory can have a different user if created by the Manager, 
        // but it should always have group boinc_master.
        if (sbuf.st_gid != boinc_master_gid)
            return -1022;
        
        // The top-level BOINC Data directory should have permission 771 or 571
        if ((sbuf.st_mode & 0577) != 0571)
            return -1023;
            
    } else {

        if (sbuf.st_uid != boinc_master_uid)
            return -1022;

    }

    snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, PROJECTS_DIR);
    retval = stat(full_path, &sbuf);
    if (!retval) {
        // Client can create projects directory if it does not yet exist.  
        //
        if (use_sandbox) {
            if (sbuf.st_gid != boinc_project_gid)
                return -1024;

        if ((sbuf.st_mode & 0777) != 0770)
            return -1025;
        }
        
        if (sbuf.st_uid != boinc_master_uid)
            return -1026;

        // Step through project directories
        retval = CheckNestedDirectories(full_path, 1, use_sandbox, isManager, path_to_error, len);
        if (retval)
            return retval;
    }

    snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, SLOTS_DIR);
    retval = stat(full_path, &sbuf);
    if (! retval) {                 // Client can create slots directory if it does not yet exist.  
       if (use_sandbox) {
            if (sbuf.st_gid != boinc_project_gid)
                return -1027;

            if ((sbuf.st_mode & 0777) != 0770)
                return -1028;
        }
        
        if (sbuf.st_uid != boinc_master_uid)
            return -1029;

        // Step through slot directories
        retval = CheckNestedDirectories(full_path, 1, use_sandbox, isManager, path_to_error, len);
        if (retval)
            return retval;
    }

    snprintf(full_path, sizeof(full_path),
        "%s/%s", dir_path, GUI_RPC_PASSWD_FILE
    );
    retval = stat(full_path, &sbuf);
    if (! retval) {                 // Client can create RPC password file if it does not yet exist.  
        if (use_sandbox) {
            if (sbuf.st_gid != boinc_master_gid)
                return -1030;

            if ((sbuf.st_mode & 0777) != 0660)
                return -1032;
        } else {
            if ((sbuf.st_mode & 0717) != 0600)
                return -1032;
        }
        
        if (sbuf.st_uid != boinc_master_uid)
            return -1031;
    }

    if (use_sandbox) {
        snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, SWITCHER_DIR);
        retval = stat(full_path, &sbuf);
        if (retval)
            return -1033;
          
        if (sbuf.st_gid != boinc_master_gid)
            return -1034;

        if (sbuf.st_uid != boinc_master_uid)
            return -1035;

        if ((sbuf.st_mode & 0777) != 0550)
            return -1036;

        strlcat(full_path, "/", sizeof(full_path));
        strlcat(full_path, SWITCHER_FILE_NAME, sizeof(full_path));
        retval = stat(full_path, &sbuf);
        if (retval)
            return -1037;
        
        if (sbuf.st_gid != boinc_master_gid)
            return -1038;

        if (sbuf.st_uid != 0)   // root
            return -1039;

        if ((sbuf.st_mode & 07777) != 04050)
            return -1040;

        snprintf(full_path, sizeof(full_path),
            "%s/%s/%s", dir_path, SWITCHER_DIR, SETPROJECTGRP_FILE_NAME
        );
        retval = stat(full_path, &sbuf);
        if (retval)
            return -1041;
        
        if (sbuf.st_gid != boinc_project_gid)
            return -1042;

        if (sbuf.st_uid != boinc_master_uid)
            return -1043;

        if ((sbuf.st_mode & 07777) != 02500)
            return -1044;

#ifdef __APPLE__
#if 0       // AppStats is deprecated as of version 5.8.15
        strlcat(full_path, "/", sizeof(full_path));
        strlcat(full_path, APP_STATS_FILE_NAME, sizeof(full_path));
        retval = stat(full_path, &sbuf);
        if (retval)
            return -1045;
        
        if (sbuf.st_gid != boinc_master_gid)
            return -1046;

        if (sbuf.st_uid != 0)   // AppStats application must be setuid root
            return -1047;

        if ((sbuf.st_mode & 07777) != 04550)
            return -1048;
#endif
#endif  // __APPLE__

        snprintf(full_path, sizeof(full_path),
            "%s/%s", dir_path, SS_CONFIG_FILE
        );

        retval = stat(full_path, &sbuf);
        if (!retval) {
            if (sbuf.st_uid != boinc_master_uid)
                return -1051;

            if (sbuf.st_gid != boinc_master_gid)
                return -1052;

            if ((sbuf.st_mode & 0777) != 0664)
                return -1053;
        }   // Screensaver config file ss_config.xml exists
        
    }       // if (use_sandbox)
    
    return 0;
}
Пример #14
0
// Pass NULL for path when calling this routine from within BOINC Manager
int SetBOINCAppOwnersGroupsAndPermissions(char *path) {
    char                    fullpath[MAXPATHLEN];
    char                    dir_path[MAXPATHLEN];
    char                    buf1[80];
    ProcessSerialNumber     ourPSN;
    FSRef                   ourFSRef, ref;
    char                    *p;
    Boolean                 isDirectory;
    OSStatus                err = noErr;
    
#define NUMBRANDS 3

char *saverName[NUMBRANDS];

saverName[0] = "BOINCSaver";
saverName[1] = "GridRepublic";
saverName[2] = "Progress Thru Processors";

#ifdef _DEBUG
    err = SetFakeMasterNames();
    if (err)
        return err;
#endif

    if (path == NULL) {        // NULL means we were called from within BOINC Manager
        // Get the full path to this application's bundle (BOINC Manager's bundle)
        err = GetCurrentProcess (&ourPSN);
        if (err)
            return err;          // Should never happen

        err = GetProcessBundleLocation(&ourPSN, &ourFSRef);
        if (err)
            return err;          // Should never happen
        
        err = FSRefMakePath (&ourFSRef, (UInt8*)dir_path, sizeof(dir_path));
        if (err)
            return err;          // Should never happen
    } else
        strlcpy(dir_path, path, MAXPATHLEN);    // Path to BOINC Manager's bundle was passed as argument
        
    if (strlen(fullpath) >= (MAXPATHLEN-1)) {
        ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to Manager is too long");
        return -1;
    }

    strlcpy(fullpath, dir_path, sizeof(fullpath));

#ifdef _DEBUG
    // chmod -R u=rwx,g=rwx,o=rx path/BOINCManager.app
    // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
    // Set read, write permission for user;  read and execute permission for group and others
    err = DoPrivilegedExec(chmodPath, "-R", "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL);
#else
    // chmod -R u=rx,g=rx,o=rx path/BOINCManager.app
    // 0555 = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
    // Set read, write permission for user;  read and execute permission for group and others
    err = DoPrivilegedExec(chmodPath, "-R", "u=rx,g=rx,o=rx", fullpath, NULL, NULL, NULL);
#endif
    if (err)
        return err;

    // Get the full path to BOINC Manager executable inside this application's bundle
    strlcat(fullpath, "/Contents/MacOS/", sizeof(fullpath));
    // To allow for branding, assume name of executable inside bundle is same as name of bundle
    p = strrchr(dir_path, '/');         // Assume name of executable inside bundle is same as name of bundle
    if (p == NULL)
        p = dir_path - 1;
    strlcat(fullpath, p+1, sizeof(fullpath));
    p = strrchr(fullpath, '.');         // Strip off  bundle extension (".app")
    if (p)
        *p = '\0'; 

    sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name);
    // chown boinc_master:boinc_master path/BOINCManager.app/Contents/MacOS/BOINCManager
    err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
    if (err)
        return err;

#ifdef _DEBUG
        // chmod u=rwx,g=rwx,o=rx path/BOINCManager.app/Contents/MacOS/BOINCManager
        // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set read, write and execute permission for user & group, read & execute for others
        err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#else
        // chmod u=rx,g=rx,o=rx path/BOINCManager.app/Contents/MacOS/BOINCManager
        // 0555 = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set read and execute permission for user, group & others
        err = DoPrivilegedExec(chmodPath, "u=rx,g=rx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#endif
    if (err)
        return err;

    // Get the full path to BOINC Clients inside this application's bundle
    strlcpy(fullpath, dir_path, sizeof(fullpath));
    strlcat(fullpath, "/Contents/Resources/boinc", sizeof(fullpath));
    if (strlen(fullpath) >= (MAXPATHLEN-1)) {
        ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to client is too long");
        return -1;
    }
    
    sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name);
    // chown boinc_master:boinc_master path/BOINCManager.app/Contents/Resources/boinc
    err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
    if (err)
        return err;

#ifdef _DEBUG
        // chmod u=rwsx,g=rwsx,o=rx path/BOINCManager.app/Contents/Resources/boinc
        // 06775 = S_ISUID | S_ISGID | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set setuid-on-execution, setgid-on-execution plus read, write and execute permission for user & group, read & execute for others
        err = DoPrivilegedExec(chmodPath, "u=rwsx,g=rwsx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#else
        // chmod u=rsx,g=rsx,o=rx path/BOINCManager.app/Contents/Resources/boinc
        // 06555 = S_ISUID | S_ISGID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set setuid-on-execution, setgid-on-execution plus read and execute permission for user, group & others
        err = DoPrivilegedExec(chmodPath, "u=rsx,g=rsx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#endif
    if (err)
        return err;

    for (int i=0; i<NUMBRANDS; i++) {
        // Version 6 screensaver has its own embedded switcher application, but older versions don't.
        // We don't allow unauthorized users to run the switcher application in the BOINC Data directory 
        // because they could use it to run as user & group boinc_project and damage project files.
        // The screensaver's switcher application runs as user and group "nobody" to avoid this risk.

        // Does switcher exist in screensaver bundle?
        sprintf(fullpath, "/Library/Screen Savers/%s.saver/Contents/Resources/gfx_switcher", saverName[i]);
        err = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory);   // Does it exist?
        if ((err == noErr) && (! isDirectory)) {
#ifdef _DEBUG
            sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name);
            // chown boinc_master:boinc_master "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
            if (err)
                return err;

            // chmod u=rwx,g=rwx,o=rx "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH
            // Set read, write and execute permission for user & group;  read and execute permission for others
            err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL, NULL);
            if (err)
                return err;
#else
            sprintf(buf1, "root:%s", boinc_master_group_name);
            // chown root:boinc_master "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
            if (err)
                return err;

            // chmod u=rsx,g=rx,o=rx "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            // 04555 = S_ISUID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
            // Set setuid-on-execution plus read and execute permission for user, group & others
            err = DoPrivilegedExec(chmodPath, "u=rsx,g=rx,o=rx", fullpath, NULL, NULL, NULL, NULL);
            if (err)
                return err;
#endif
        }
    }
    
    return noErr;
}
Пример #15
0
int main(int argc, char *argv[])
{
    Boolean                 Success;
    ProcessSerialNumber     ourProcess, installerPSN;
    short                   itemHit;
    long                    brandID = 0;
    int                     i;
    pid_t                   installerPID = 0, coreClientPID = 0, waitPermissionsPID = 0;
    FSRef                   fileRef;
    OSStatus                err, err_fsref;
    FILE                    *f;
    char                    s[256];
    char                    *q;
#ifdef SANDBOX
    uid_t                   saved_euid, saved_uid, b_m_uid;
    passwd                  *pw;
    int                     finalInstallAction;
    DialogRef               theWin;

#else   // SANDBOX
    group                   *grp;
#endif  // SANDBOX

    appName[0] = "/Applications/BOINCManager.app";
    appNameEscaped[0] = "/Applications/BOINCManager.app";
    brandName[0] = "BOINC";
    saverName[0] = "BOINCSaver";
    saverNameEscaped[0] = "BOINCSaver";
    receiptNameEscaped[0] = "/Library/Receipts/BOINC.pkg";

    appName[1] = "/Applications/GridRepublic Desktop.app";
    appNameEscaped[1] = "/Applications/GridRepublic\\ Desktop.app";
    brandName[1] = "GridRepublic";
    saverName[1] = "GridRepublic";
    saverNameEscaped[1] = "GridRepublic";
    receiptNameEscaped[1] = "/Library/Receipts/GridRepublic.pkg";

    appName[2] = "/Applications/Progress Thru Processors Desktop.app";
    appNameEscaped[2] = "/Applications/Progress\\ Thru\\ Processors\\ Desktop.app";
    brandName[2] = "Progress Thru Processors";
    saverName[2] = "Progress Thru Processors";
    saverNameEscaped[2] = "Progress\\ Thru\\ Processors";
    receiptNameEscaped[2] = "/Library/Receipts/Progress\\ Thru\\ Processors.pkg";

    ::GetCurrentProcess (&ourProcess);
    
    // getlogin() gives unreliable results under OS 10.6.2, so use environment
    strncpy(loginName, getenv("USER"), sizeof(loginName)-1);

    err = Gestalt(gestaltSystemVersion, &OSVersion);
    if (err != noErr)
        return err;

    for (i=0; i<argc; i++) {
        if (strcmp(argv[i], "-part2") == 0)
            return DeleteReceipt();
    }

    Initialize();

    QuitBOINCManager('BNC!'); // Quit any old instance of BOINC manager
    sleep(2);

    // Core Client may still be running if it was started without Manager
    coreClientPID = FindProcessPID("boinc", 0);
    if (coreClientPID)
        kill(coreClientPID, SIGTERM);   // boinc catches SIGTERM & exits gracefully

    err = FindProcess ('APPL', 'xins', &installerPSN);
    if (err == noErr)
        err = GetProcessPID(&installerPSN , &installerPID);

    brandID = GetBrandID();
    
    if ((brandID < 0) || (brandID >= NUMBRANDS)) {       // Safety check
        brandID = 0;
    }
    
    if (OSVersion < 0x1040) {
        ::SetFrontProcess(&ourProcess);
        // Remove everything we've installed
        // "\pSorry, this version of GridRepublic requires system 10.4.0 or higher."
        s[0] = sprintf(s+1, "Sorry, this version of %s requires system 10.4.0 or higher.", brandName[brandID]);
        StandardAlert (kAlertStopAlert, (StringPtr)s, NULL, NULL, &itemHit);

        // "rm -rf /Applications/GridRepublic\\ Desktop.app"
        sprintf(s, "rm -rf %s", appNameEscaped[brandID]);
        system (s);
        
        // "rm -rf /Library/Screen\\ Savers/GridRepublic.saver"
        sprintf(s, "rm -rf /Library/Screen\\ Savers/%s.saver", saverNameEscaped[brandID]);
        system (s);
        
        // "rm -rf /Library/Receipts/GridRepublic.pkg"
        sprintf(s, "rm -rf %s", receiptNameEscaped[brandID]);
        system (s);

        // We don't customize BOINC Data directory name for branding
        system ("rm -rf /Library/Application\\ Support/BOINC\\ Data");

        err = kill(installerPID, SIGKILL);

	ExitToShell();
    }
    
    sleep (2);

    // Install all_projects_list.xml file, but only if one doesn't 
    // already exist, since a pre-existing one is probably newer.
    f = fopen("/Library/Application Support/BOINC Data/all_projects_list.xml", "r");
    if (f) {
        fclose(f);      // Already exists
    } else {
        system ("cp -fp Contents/Resources/all_projects_list.xml /Library/Application\\ Support/BOINC\\ Data/");
        system ("chmod a-x /Library/Application\\ Support/BOINC\\ Data/all_projects_list.xml");
    }
    
    Success = false;
    
#ifdef SANDBOX

    CheckUserAndGroupConflicts();

    for (i=0; i<5; ++i) {
        err = CreateBOINCUsersAndGroups();
        if (err != noErr) {
//          print_to_log_file("CreateBOINCUsersAndGroups returned %d (repetition=%d)", err, i);
            continue;
        }
        
        // err = SetBOINCAppOwnersGroupsAndPermissions("/Applications/GridRepublic Desktop.app");
        err = SetBOINCAppOwnersGroupsAndPermissions(appName[brandID]);
        
        if (err != noErr) {
//          print_to_log_file("SetBOINCAppOwnersGroupsAndPermissions returned %d (repetition=%d)", err, i);
            continue;
        }

        err = SetBOINCDataOwnersGroupsAndPermissions();
        if (err != noErr) {
//          print_to_log_file("SetBOINCDataOwnersGroupsAndPermissions returned %d (repetition=%d)", err, i);
            continue;
        }
        
        err = check_security(appName[brandID], "/Library/Application Support/BOINC Data", true, false);
        if (err == noErr)
            break;
//          print_to_log_file("check_security returned %d (repetition=%d)", err, i);
    }
    
#else   // ! defined(SANDBOX)

    // The BOINC Manager and Core Client have the set-user-ID-on-execution 
    // flag set, so their ownership is important and must match the 
    // ownership of the BOINC Data directory.
    
    // Find an appropriate admin user to set as owner of installed files
    // First, try the user currently logged in
    grp = getgrnam("admin");
    i = 0;
    while ((p = grp->gr_mem[i]) != NULL) {   // Step through all users in group admin
        if (strcmp(p, loginName) == 0) {
            Success = true;     // Logged in user is a member of group admin
            break;
        }
        ++i;
    }
    
    // If currently logged in user is not admin, use first non-root admin user
    if (!Success) {
        i = 0;
        while ((p = grp->gr_mem[i]) != NULL) {   // Step through all users in group admin
            if (strcmp(p, "root") != 0)
                break;
            ++i;
        }
    }

    // Set owner of branded BOINCManager and contents, including core client
    // "chown -Rf username /Applications/GridRepublic\\ Desktop.app"
    sprintf(s, "chown -Rf %s %s", p, appNameEscaped[brandID]);
    system (s);

    // Set owner of BOINC Screen Saver
    // "chown -Rf username /Library/Screen\\ Savers/GridRepublic.saver"
    sprintf(s, "chown -Rf %s /Library/Screen\\ Savers/%s.saver", p, saverNameEscaped[brandID]);
    system (s);

    //  We don't customize BOINC Data directory name for branding
    // "chown -Rf username /Library/Application\\ Support/BOINC\\ Data"
    sprintf(s, "chown -Rf %s /Library/Application\\ Support/BOINC\\ Data", p);
    system (s);

    // "chmod -R a+s /Applications/GridRepublic\\ Desktop.app"
    sprintf(s, "chmod -R a+s %s", appNameEscaped[brandID]);
    system (s);

#endif   // ! defined(SANDBOX)

    // Remove any branded versions of BOINC other than ours (i.e., old versions) 
    for (i=0; i< NUMBRANDS; i++) {
        if (i == brandID) continue;
        
        // "rm -rf /Applications/GridRepublic\\ Desktop.app"
        sprintf(s, "rm -rf %s", appNameEscaped[i]);
        system (s);
        
        // "rm -rf /Library/Screen\\ Savers/GridRepublic.saver"
        sprintf(s, "rm -rf /Library/Screen\\ Savers/%s.saver", saverNameEscaped[i]);
        system (s);
    }
    
   if (brandID == 0) {  // Installing generic BOINC
        system ("rm -f /Library/Application\\ Support/BOINC\\ Data/Branding");
    }
    
    // err_fsref = FSPathMakeRef((StringPtr)"/Applications/GridRepublic Desktop.app", &fileRef, NULL);
    err_fsref = FSPathMakeRef((StringPtr)appName[brandID], &fileRef, NULL);
    
    if (err_fsref == noErr)
        err = LSRegisterFSRef(&fileRef, true);
    
    err = UpdateAllVisibleUsers(brandID);
    if (err != noErr)
        return err;
 
#ifdef SANDBOX
    err = CheckLogoutRequirement(&finalInstallAction);
    
    if (finalInstallAction == launchWhenDone) {
        // Wait for BOINC's RPC socket address to become available to user boinc_master, in
        // case we are upgrading from a version which did not run as user boinc_master.
        saved_uid = getuid();
        saved_euid = geteuid();
        
        pw = getpwnam("boinc_master");
        b_m_uid = pw->pw_uid;
        seteuid(b_m_uid);
        
        for (i=0; i<120; i++) {
            err = TestRPCBind();
            if (err == noErr)
                break;
            
            sleep(1);
        }
        
        seteuid(saved_euid);

        ProcessSerialNumber ourPSN;
        ProcessInfoRec      pInfo;
        FSRef               ourFSRef, theFSRef;
        char                thePath[MAXPATHLEN];
        
        // Get the full path to this PostInstall application's bundle
        err = GetCurrentProcess (&ourPSN);
        if (err)
            return -1000;          // Should never happen
        
        memset(&pInfo, 0, sizeof(pInfo));
        pInfo.processInfoLength = sizeof( ProcessInfoRec );
        err = GetProcessInformation(&ourPSN, &pInfo);
        if (err)
            return -1001;          // Should never happen
        
        err = GetProcessBundleLocation(&ourPSN, &ourFSRef);
        if (err)
            return -1002;          // Should never happen

        err = FSRefMakePath (&ourFSRef, (UInt8*)thePath, sizeof(thePath));
        if (err)
            return -1003;          // Should never happen
        
        q = strrchr(thePath, '/');
        if (q == NULL)
            return -1004;          // Should never happen

        *++q = '\0';
        strlcat(thePath, "WaitPermissions.app", sizeof(thePath));
        err = FSPathMakeRef((StringPtr)thePath, &theFSRef, NULL);
        
        // When we first create the boinc_master group and add the current user to the 
        // new group, there is a delay before the new group membership is recognized.  
        // If we launch the BOINC Manager too soon, it will fail with a -1037 permissions 
        // error, so we wait until the current user can access the switcher application.
        // Apparently, in order to get the changed permissions / group membership, we must 
        // launch a new process belonging to the user.  It may also need to be in a new 
        // process group or new session. Neither system() nor popen() works, even after 
        // setting the uid and euid back to the logged in user, but LSOpenFSRef() does.
        // The WaitPermissions application loops until it can access the switcher 
        // application.
        err = LSOpenFSRef(&theFSRef, NULL);

        waitPermissionsStartTime = time(NULL);
        for (i=0; i<15; i++) {     // Show "Please wait..." alert after 15 seconds
            waitPermissionsPID = FindProcessPID("WaitPermissions", 0);
            if (waitPermissionsPID == 0) {
                return 0;
            }
            sleep(1);
        }
        
        CreateStandardAlert(kAlertNoteAlert, CFSTR("Finishing install.  Please wait ..."), CFSTR("This may take a few more minutes."), NULL, &theWin);
        HideDialogItem(theWin, kStdOkItemIndex);
        RemoveDialogItems(theWin, kStdOkItemIndex, 1, false);
        RunStandardAlert(theWin, &myFilterProc, &itemHit);

    }
#endif   // SANDBOX
    
    return 0;
}
Пример #16
0
int main(int argc, char *argv[])
{
    char                    pkgPath[MAXPATHLEN];
    char                    temp[MAXPATHLEN];
    char                    brand[64], s[256];
    char                    *p;
    ProcessSerialNumber     ourPSN;
    FSRef                   ourFSRef;
    OSStatus                err = noErr;
    Boolean                 restartNeeded = true;
    FILE                    *restartNeededFile;

    Initialize();

    // Get the full path to Installer package inside this application's bundle
    err = GetCurrentProcess (&ourPSN);
    if (err == noErr)
        err = GetProcessBundleLocation(&ourPSN, &ourFSRef);

    if (err == noErr)
        err = FSRefMakePath (&ourFSRef, (UInt8*)pkgPath, sizeof(pkgPath));

    strlcpy(temp, pkgPath, sizeof(temp));

    strlcat(pkgPath, "/Contents/Resources/", sizeof(pkgPath));

   // To allow for branding, assume name of installer package inside bundle corresponds to name of this application
    p = strrchr(temp, '/');         // Point to name of this application (e.g., "BOINC Installer.app")
    if (p == NULL)
        p = temp - 1;
    strlcpy(brand, p+1, sizeof(brand));
    strlcat(pkgPath, p+1, sizeof(pkgPath));
    p = strrchr(pkgPath, ' ');         // Strip off last space character and everything following
    if (p)
        *p = '\0'; 

    p = strstr(brand, " Installer.app");  // Strip off trailing " Installer.app"
    if (p)
        *p = '\0'; 
    
    strlcat(pkgPath, ".pkg", sizeof(pkgPath));
    // Expand the installer package
    system("rm -dfR /tmp/BOINC.pkg");
    system("rm -dfR /tmp/expanded_BOINC.pkg");
    sprintf(temp, "pkgutil --expand \"%s\" /tmp/expanded_BOINC.pkg", pkgPath);
    err = system(temp);

    if (err == noErr) {
        GetPreferredLanguages();
    }
    if (compareOSVersionTo(10, 5) < 0) {
        LoadPreferredLanguages();
        ::SetFrontProcess(&ourPSN);
        p = strrchr(brand, ' ');         // Strip off last space character and everything following
        if (p)
            *p = '\0'; 
        ShowMessage((char *)_("Sorry, this version of %s requires system 10.5 or higher."), brand);

        system("rm -dfR /tmp/BOINC_payload");
        return -1;
    }

    system("rm -dfR /tmp/BOINC_payload");

    // Remove previous installer package receipt so we can run installer again
    // (affects only older versions of OS X and fixes a bug in those versions)
    // "rm -rf /Library/Receipts/GridRepublic.pkg"
    sprintf(s, "rm -rf \"/Library/Receipts/%s.pkg\"", brand);
    system (s);

    restartNeeded = IsRestartNeeded();
    
    // Write a temp file to tell our PostInstall.app whether restart is needed
    restartNeededFile = fopen("/tmp/BOINC_restart_flag", "w");
    if (restartNeededFile) {
        fputs(restartNeeded ? "1\n" : "0\n", restartNeededFile);
        fclose(restartNeededFile);
    }
    
    if (restartNeeded) {
        if (err == noErr) {
            // Change onConclusion="none" to onConclusion="RequireRestart"
            err = system("sed -i \"\" s/\"onConclusion=\\\"none\\\"\"/\"onConclusion=\\\"RequireRestart\\\"\"/g /tmp/expanded_BOINC.pkg/Distribution");
        }
        if (err == noErr) {
            // Flatten the installer package
            sprintf(temp, "pkgutil --flatten /tmp/expanded_BOINC.pkg /tmp/%s.pkg", brand);
            err = system(temp);
            
            system("rm -fR /tmp/expanded_BOINC.pkg");
        }

        if (err == noErr) {
            sprintf(temp, "open \"/tmp/%s.pkg\" &", brand);
            system(temp);
            return 0;
        }
    }

    sprintf(temp, "open \"%s\" &", pkgPath);
    system(temp);
    
    return err;
}