pid_t WBProcessGetProcessIdentifierForBundleIdentifier(CFStringRef bundleId) { pid_t pid = 0; ProcessSerialNumber psn = WBProcessGetProcessWithBundleIdentifier(bundleId); if (psn.lowLongOfPSN != kNoProcess && noErr == GetProcessPID(&psn, &pid)) return pid; return 0; }
void Overlay::toggleShow() { if (g.ocIntercept) { g.ocIntercept->hideGui(); } else { foreach(OverlayClient *oc, qlClients) { if (oc->uiPid) { #if defined(Q_OS_WIN) HWND hwnd = GetForegroundWindow(); DWORD pid = 0; GetWindowThreadProcessId(hwnd, &pid); if (pid != oc->uiPid) continue; #elif defined(Q_OS_MAC) pid_t pid = 0; ProcessSerialNumber psn; GetFrontProcess(&psn); GetProcessPID(&psn, &pid); if (pid != oc->uiPid) continue; #if 0 // Fullscreen only. if (! CGDisplayIsCaptured(CGMainDisplayID())) continue; #endif #endif oc->showGui(); return; } } } }
pid_t HelperMacX::getKeepassxPID(){ if (0 == keepassxPID) { ProcessSerialNumber processSerialNumber; GetCurrentProcess(&processSerialNumber); GetProcessPID(&processSerialNumber, &keepassxPID); } return keepassxPID; }
static AXUIElementRef getFrontMostApp () { pid_t pid; ProcessSerialNumber psn; GetFrontProcess(&psn); GetProcessPID(&psn, &pid); return AXUIElementCreateApplication(pid); }
// Send a Quit AppleEvent to the process which called this module // (i.e., tell the ScreenSaver engine to quit) OSErr CScreensaver::KillScreenSaver() { ProcessSerialNumber thisPSN; pid_t thisPID; OSErr err = noErr; GetCurrentProcess(&thisPSN); err = GetProcessPID(&thisPSN , &thisPID); if (err == noErr) err = kill(thisPID, SIGABRT); // SIGINT return err; }
pid_t getFrontmostPID(void) { pid_t pid; ProcessSerialNumber psn; GetFrontProcess(&psn); GetProcessPID(&psn, &pid); return pid; }
internal void CarbonApplicationLaunched(ProcessSerialNumber PSN) { Str255 ProcessName = {}; ProcessInfoRec ProcessInfo = {}; ProcessInfo.processInfoLength = sizeof(ProcessInfoRec); ProcessInfo.processName = ProcessName; /* NOTE(koekeishiya): Deprecated, consider switching to * CFDictionaryRef ProcessInformationCopyDictionary(const ProcessSerialNumber *PSN, UInt32 infoToReturn) */ GetProcessInformation(&PSN, &ProcessInfo); char ProcessNameCString[256] = {0}; if(ProcessInfo.processName) CopyPascalStringToC(ProcessInfo.processName, ProcessNameCString); std::string Name = ProcessNameCString; /* NOTE(koekeishiya): Check if we should care about this process. */ if((!IsProcessWhitelisted(Name)) && ((ProcessInfo.processMode & modeOnlyBackground) != 0)) return; pid_t PID = 0; GetProcessPID(&PSN, &PID); /* printf("Carbon: Application launched %s\n", Name.c_str()); printf("%d: modeReserved\n", ProcessInfo.processMode & modeReserved); printf("%d: modeControlPanel\n", ProcessInfo.processMode & modeControlPanel); printf("%d: modeLaunchDontSwitch\n", ProcessInfo.processMode & modeLaunchDontSwitch); printf("%d: modeDeskAccessory\n", ProcessInfo.processMode & modeDeskAccessory); printf("%d: modeMultiLaunch\n", ProcessInfo.processMode & modeMultiLaunch); printf("%d: modeNeedSuspendResume\n", ProcessInfo.processMode & modeNeedSuspendResume); printf("%d: modeCanBackground\n", ProcessInfo.processMode & modeCanBackground); printf("%d: modeDoesActivateOnFGSwitch\n", ProcessInfo.processMode & modeDoesActivateOnFGSwitch); printf("%d: modeOnlyBackground\n", ProcessInfo.processMode & modeOnlyBackground); printf("%d: modeGetFrontClicks\n", ProcessInfo.processMode & modeGetFrontClicks); printf("%d: modeGetAppDiedMsg\n", ProcessInfo.processMode & modeGetAppDiedMsg); printf("%d: mode32BitCompatible\n", ProcessInfo.processMode & mode32BitCompatible); printf("%d: modeHighLevelEventAware\n", ProcessInfo.processMode & modeHighLevelEventAware); printf("%d: modeLocalAndRemoteHLEvents\n", ProcessInfo.processMode & modeLocalAndRemoteHLEvents); printf("%d: modeStationeryAware\n", ProcessInfo.processMode & modeStationeryAware); printf("%d: modeUseTextEditServices\n", ProcessInfo.processMode & modeUseTextEditServices); printf("%d: modeDisplayManagerAware\n", ProcessInfo.processMode & modeDisplayManagerAware); */ (*Applications)[PID] = AXLibConstructApplication(PID, Name); ax_application *Application = &(*Applications)[PID]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ if(AXLibInitializeApplication(Application->PID)) AXLibInitializedApplication(Application); });
// After installation has completed, delete the installer receipt. // If we don't need to logout the user, also launch BOINC Manager. int DeleteReceipt() { ProcessSerialNumber installerPSN; long brandID = 0; int i; pid_t installerPID = 0; OSStatus err; int finalInstallAction; FSRef fileRef; char s[256]; struct stat sbuf; OSStatus err_fsref; Initialize(); err = CheckLogoutRequirement(&finalInstallAction); err = FindProcess ('APPL', 'xins', &installerPSN); if (err == noErr) err = GetProcessPID(&installerPSN , &installerPID); // Launch BOINC Manager when user closes installer or after 15 seconds for (i=0; i<15; i++) { // Wait 15 seconds max for installer to quit sleep (1); if (err == noErr) if (FindProcessPID(NULL, installerPID) == 0) break; } brandID = GetBrandID(); // Remove installer package receipt so we can run installer again if needed to fix permissions // "rm -rf /Library/Receipts/GridRepublic.pkg" sprintf(s, "rm -rf %s", receiptNameEscaped[brandID]); system (s); // err_fsref = FSPathMakeRef((StringPtr)"/Applications/GridRepublic Desktop.app", &fileRef, NULL); err_fsref = FSPathMakeRef((StringPtr)appName[brandID], &fileRef, NULL); if (finalInstallAction == launchWhenDone) { // If system is set up to run BOINC Client as a daemon using launchd, launch it // as a daemon and allow time for client to start before launching BOINC Manager. err = stat("/Library/LaunchDaemons/edu.berkeley.boinc.plist", &sbuf); if (err == noErr) { system("launchctl unload /Library/LaunchDaemons/edu.berkeley.boinc.plist"); i = system("launchctl load /Library/LaunchDaemons/edu.berkeley.boinc.plist"); if (i == 0) sleep (2); } err = LSOpenFSRef(&fileRef, NULL); } return 0; }
void checkFinder() { ProcessSerialNumber psn; FindProcessBySignature( 'FNDR', 'MACS', &psn ); pid_t pid; GetProcessPID(&psn, &pid); if (pid != g_lastFinderPid) { system("\"/Library/Application Support/Liferay/LiferayFinderPlugin.app/Contents/MacOS/LiferayFinderPlugin\""); g_lastFinderPid = pid; } }
pid_t MouseEventTool::getPid() { pid_t pid; ProcessSerialNumber proc; OSStatus err; err = GetCurrentProcess(&proc); if (err) { return -1; } err = GetProcessPID(&proc, &pid); if (err) { return -1; } return pid; }
int is_mplayer_front(void) { ProcessSerialNumber myProc, frProc; Boolean sameProc; pid_t parentPID; if (GetFrontProcess(&frProc) == noErr && GetCurrentProcess(&myProc) == noErr && SameProcess(&frProc, &myProc, &sameProc) == noErr) { if (sameProc) return 1; // If MPlayer is running in slave mode, also check parent process. if (slave_mode && GetProcessPID(&frProc, &parentPID) == noErr) return parentPID==getppid(); } return 0; }
void killDock() { mach_error_t err = 0; // Find target by signature. ProcessSerialNumber psn; if( !err ) err = mac_err( FindProcessBySignature( 'APPL', 'dock', &psn )); // Convert PSN to PID. pid_t dockpid; if( !err ) err = mac_err( GetProcessPID( &psn, &dockpid )); if( !err ) printf( "pid: %ld\n", (long) dockpid ); kill(dockpid, SIGKILL); }
int IsSkypeRunning(void) { OSStatus status = noErr; ProcessSerialNumber psn = {kNoProcess, kNoProcess}; unsigned int procNameLength = 32; unsigned char procName[procNameLength]; unsigned int i = 0; ProcessInfoRec info; info.processInfoLength = sizeof(ProcessInfoRec); info.processName = procName; #if __LP64__ info.processAppRef = NULL; #else info.processAppSpec = NULL; #endif pid_t pid = 0; while(status == noErr) { for(i = 0; i < procNameLength; i++) procName[i] = '\0'; status = GetNextProcess(&psn); if (status == noErr) { if (GetProcessInformation(&psn, &info) == noErr) { //for some reason first character is poisioned if (g_str_equal((char *)&procName[1], "Skype")) { if (GetProcessPID(&psn, &pid) == noErr) { return (int)pid; } } } } } return 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; }
void checkFinder(void) { ProcessSerialNumber psn; FindProcessBySignature('FNDR', 'MACS', &psn); pid_t pid; GetProcessPID(&psn, &pid); if (pid != g_lastFinderPid) { sleep(1); int err = system("\"/Library/Application Support/Liferay/LiferayFinderPlugin.app/Contents/MacOS/LiferayFinderPlugin\""); char buff[40]; sprintf(buff, "error: %d", err); g_lastFinderPid = pid; } }
int main (int argc, const char * argv[]) { // Parse arguments if (argc != 6) { printf("Syntax error\n"); exit(EXIT_FAILURE); } char *browser, *url, *filename, *cmd; int xRes, yRes; ProcessSerialNumber browserPSN; pid_t browserPID; browser = argv[1]; url = argv[4]; filename = argv[5]; xRes = atoi(argv[2]); yRes = atoi(argv[3]); changeResolution(xRes, yRes); browserPSN = openUrl(browser, url); int sleepPeriod = SLEEP_PERIOD; while ((sleepPeriod = sleep(sleepPeriod)) != 0); cmd = malloc((40 + strlen(filename)) * sizeof(char)); sprintf(cmd, "/usr/sbin/screencapture -x -tjpg %s", filename); system(cmd); GetProcessPID(&browserPSN, &browserPID); // F**k Apple events, can't get'em right kill(browserPID, SIGTERM); sleep(1); KillProcess(&browserPSN); return 0; }
OSErr injectCode() { mach_error_t err = err_none; //printf("Attempting to install Dock patch...\n"); // Get the main bundle for the app. CFBundleRef mainBundle = NULL; if(!err) { mainBundle = CFBundleGetMainBundle(); if( !mainBundle ) err = err_couldnt_load_main_bundle; } // Find our injection bundle by name. CFURLRef injectionURL = NULL; if( !err ) { injectionURL = CFBundleCopyResourceURL( mainBundle, CFSTR("DockExtension.bundle"), NULL, NULL ); if( !injectionURL ) err = err_couldnt_find_injection_bundle; } // Create injection bundle instance. CFBundleRef injectionBundle = NULL; if( !err ) { injectionBundle = CFBundleCreate( kCFAllocatorDefault, injectionURL ); if( !injectionBundle ) err = err_couldnt_load_injection_bundle; } // Load the thread code injection. void *injectionCode = NULL; if( !err ) { injectionCode = CFBundleGetFunctionPointerForName( injectionBundle, CFSTR( INJECT_ENTRY_SYMBOL )); if( injectionCode == NULL ) err = err_couldnt_find_injectedThread_symbol; } // Find target by signature. ProcessSerialNumber psn; if( !err ) err = mac_err( FindProcessBySignature( 'APPL', 'dock', &psn )); // Convert PSN to PID. pid_t dockpid; if( !err ) err = mac_err( GetProcessPID( &psn, &dockpid )); //if( !err ) // printf( "pid: %ld\n", (long) dockpid ); // Inject the code. if( !err ) err = mach_inject( injectionCode, NULL, 0, dockpid, 0 ); if(err) { printf("Failed!\n"); } // Clean up. if( injectionBundle ) CFRelease( injectionBundle ); if( injectionURL ) CFRelease( injectionURL ); if( mainBundle ) CFRelease( mainBundle ); return err; }
/** Check if a process with a given name is running * @param names list of names to check * @return list of detected processes. */ QStringList Utils::findRunningProcess(QStringList names) { QStringList processlist; QStringList found; #if defined(Q_OS_WIN32) HANDLE hdl; PROCESSENTRY32 entry; bool result; hdl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hdl == INVALID_HANDLE_VALUE) { qDebug() << "[Utils] CreateToolhelp32Snapshot failed."; return found; } entry.dwSize = sizeof(PROCESSENTRY32); entry.szExeFile[0] = '\0'; if(!Process32First(hdl, &entry)) { qDebug() << "[Utils] Process32First failed."; return found; } processlist.append(QString::fromWCharArray(entry.szExeFile)); do { entry.dwSize = sizeof(PROCESSENTRY32); entry.szExeFile[0] = '\0'; result = Process32Next(hdl, &entry); if(result) { processlist.append(QString::fromWCharArray(entry.szExeFile)); } } while(result); CloseHandle(hdl); #endif #if defined(Q_OS_MACX) ProcessSerialNumber psn = { 0, kNoProcess }; OSErr err; do { pid_t pid; err = GetNextProcess(&psn); err = GetProcessPID(&psn, &pid); if(err == noErr) { char buf[32] = {0}; ProcessInfoRec info; memset(&info, 0, sizeof(ProcessInfoRec)); info.processName = (unsigned char*)buf; info.processInfoLength = sizeof(ProcessInfoRec); err = GetProcessInformation(&psn, &info); if(err == noErr) { // some processes start with nonprintable characters. Skip those. int i; for(i = 0; i < 32; i++) { if(isprint(buf[i])) break; } // avoid adding duplicates. QString process = QString::fromUtf8(&buf[i]); if(!processlist.contains(process)) { processlist.append(process); } } } } while(err == noErr); #endif // check for given names in list of processes for(int i = 0; i < names.size(); ++i) { #if defined(Q_OS_WIN32) // the process name might be truncated. Allow the extension to be partial. int index = processlist.indexOf(QRegExp(names.at(i) + "(\\.(e(x(e?)?)?)?)?")); #else int index = processlist.indexOf(names.at(i)); #endif if(index != -1) { found.append(processlist.at(index)); } } qDebug() << "[Utils] Found listed processes running:" << found; return found; }
static OSErr QuitBOINCManager(OSType signature) { bool done = false; ProcessSerialNumber thisPSN; ProcessInfoRec thisPIR; OSErr err = noErr; Str63 thisProcessName; AEAddressDesc thisPSNDesc; AppleEvent thisQuitEvent, thisReplyEvent; thisPIR.processInfoLength = sizeof (ProcessInfoRec); thisPIR.processName = thisProcessName; thisPIR.processAppSpec = nil; thisPSN.highLongOfPSN = 0; thisPSN.lowLongOfPSN = kNoProcess; while (done == false) { err = GetNextProcess(&thisPSN); if (err == procNotFound) done = true; // apparently the demo app isn't running. Odd but not impossible else { err = GetProcessInformation(&thisPSN,&thisPIR); if (err != noErr) goto bail; if (thisPIR.processSignature == signature) { // is it or target process? err = AECreateDesc(typeProcessSerialNumber, (Ptr)&thisPSN, sizeof(thisPSN), &thisPSNDesc); if (err != noErr) goto bail; // Create the 'quit' Apple event for this process. err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &thisPSNDesc, kAutoGenerateReturnID, kAnyTransactionID, &thisQuitEvent); if (err != noErr) { AEDisposeDesc (&thisPSNDesc); goto bail; // don't know how this could happen, but limp gamely onward } // send the event err = AESend(&thisQuitEvent, &thisReplyEvent, kAEWaitReply, kAENormalPriority, kAEDefaultTimeout, 0L, 0L); AEDisposeDesc (&thisQuitEvent); AEDisposeDesc (&thisPSNDesc); #if 0 if (err == errAETimeout) { pid_t thisPID; err = GetProcessPID(&thisPSN , &thisPID); if (err == noErr) err = kill(thisPID, SIGKILL); } #endif done = true; // we've killed the process, presumably } } } bail: return err; }
int process_spawn( process_t* proc ) { static char unescaped[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.:/\\"; int i, num_args; int size; #if FOUNDATION_PLATFORM_WINDOWS wchar_t* wcmdline; wchar_t* wwd; char* cmdline = 0; #endif if( !proc ) return PROCESS_INVALID_ARGS; proc->code = PROCESS_INVALID_ARGS; if( !string_length( proc->path ) ) return proc->code; //Always escape path on Windows platforms #if FOUNDATION_PLATFORM_POSIX if( string_find_first_not_of( proc->path, unescaped, 0 ) != STRING_NPOS ) #endif { if( proc->path[0] != '"' ) proc->path = string_prepend( proc->path, "\"" ); if( proc->path[ string_length( proc->path ) - 1 ] != '"' ) proc->path = string_append( proc->path, "\"" ); } size = array_size( proc->args ); for( i = 0, num_args = 0; i < size; ++i ) { char* arg = proc->args[i]; if( !string_length( arg ) ) continue; ++num_args; if( string_find_first_not_of( arg, unescaped, 0 ) != STRING_NPOS ) { if( arg[0] != '"' ) { //Check if we need to escape " characters unsigned int pos = string_find( arg, '"', 0 ); while( pos != STRING_NPOS ) { if( arg[ pos - 1 ] != '\\' ) { char* escarg = string_substr( arg, 0, pos ); char* left = string_substr( arg, pos, STRING_NPOS ); escarg = string_append( escarg, "\\" ); escarg = string_append( escarg, left ); string_deallocate( left ); string_deallocate( arg ); arg = escarg; } pos = string_find( arg, '"', pos + 2 ); } arg = string_prepend( arg, "\"" ); arg = string_append( arg, "\"" ); proc->args[i] = arg; } } } #if FOUNDATION_PLATFORM_WINDOWS # ifndef SEE_MASK_NOASYNC # define SEE_MASK_NOASYNC 0x00000100 # endif if( !( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) ) //Don't prepend exe path to parameters if using ShellExecute cmdline = string_clone( proc->path ); //Build command line string for( i = 0; i < size; ++i ) { char* arg = proc->args[i]; if( !string_length( arg ) ) continue; if( cmdline ) cmdline = string_append( cmdline, " " ); cmdline = string_append( cmdline, arg ); } if( !string_length( proc->wd ) ) proc->wd = string_clone( environment_current_working_directory() ); wcmdline = wstring_allocate_from_string( cmdline, 0 ); wwd = wstring_allocate_from_string( proc->wd, 0 ); if( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) { SHELLEXECUTEINFOW sei; wchar_t* wverb; wchar_t* wpath; wverb = ( proc->verb && string_length( proc->verb ) ) ? wstring_allocate_from_string( proc->verb, 0 ) : 0; wpath = wstring_allocate_from_string( proc->path, 0 ); ZeroMemory( &sei, sizeof( sei ) ); sei.cbSize = sizeof(SHELLEXECUTEINFOW); sei.hwnd = 0; sei.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; sei.lpVerb = wverb; sei.lpFile = wpath; sei.lpParameters = wcmdline; sei.lpDirectory = wwd; sei.nShow = SW_SHOWNORMAL; if( !( proc->flags & PROCESS_CONSOLE ) ) sei.fMask |= SEE_MASK_NO_CONSOLE; if( proc->flags & PROCESS_STDSTREAMS ) log_warnf( 0, WARNING_UNSUPPORTED, "Unable to redirect standard in/out through pipes when using ShellExecute for process spawning" ); log_debugf( 0, "Spawn process (ShellExecute): %s %s", proc->path, cmdline ); if( !ShellExecuteExW( &sei ) ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (ShellExecute) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) ); } else { proc->hp = sei.hProcess; proc->ht = 0; proc->code = 0; } wstring_deallocate( wverb ); wstring_deallocate( wpath ); } else { STARTUPINFOW si; PROCESS_INFORMATION pi; BOOL inherit_handles = FALSE; memset( &si, 0, sizeof( si ) ); memset( &pi, 0, sizeof( pi ) ); si.cb = sizeof( si ); if( proc->flags & PROCESS_STDSTREAMS ) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = pipe_write_handle( proc->pipeout ); si.hStdError = pipe_write_handle( proc->pipeout ); si.hStdInput = pipe_read_handle( proc->pipein ); //Don't inherit wrong ends of pipes SetHandleInformation( pipe_read_handle( proc->pipeout ), HANDLE_FLAG_INHERIT, 0 ); SetHandleInformation( pipe_write_handle( proc->pipein ), HANDLE_FLAG_INHERIT, 0 ); inherit_handles = TRUE; } log_debugf( 0, "Spawn process (CreateProcess): %s %s", proc->path, cmdline ); if( !CreateProcessW( 0/*wpath*/, wcmdline, 0, 0, inherit_handles, ( proc->flags & PROCESS_CONSOLE ) ? CREATE_NEW_CONSOLE : 0, 0, wwd, &si, &pi ) ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (CreateProcess) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) ); stream_deallocate( proc->pipeout ); stream_deallocate( proc->pipein ); proc->pipeout = 0; proc->pipein = 0; } else { proc->hp = pi.hProcess; proc->ht = pi.hThread; proc->code = 0; } if( proc->pipeout ) pipe_close_write( proc->pipeout ); if( proc->pipein ) pipe_close_read( proc->pipein ); } wstring_deallocate( wcmdline ); wstring_deallocate( wwd ); string_deallocate( cmdline ); if( proc->code < 0 ) return proc->code; //Error #endif #if FOUNDATION_PLATFORM_MACOSX if( proc->flags & PROCESS_OSX_USE_OPENAPPLICATION ) { proc->pid = 0; LSApplicationParameters params; ProcessSerialNumber psn; FSRef* fsref = memory_allocate( 0, sizeof( FSRef ), 0, MEMORY_TEMPORARY | MEMORY_ZERO_INITIALIZED ); memset( ¶ms, 0, sizeof( LSApplicationParameters ) ); memset( &psn, 0, sizeof( ProcessSerialNumber ) ); char* pathstripped = string_strip( string_clone( proc->path ), "\"" ); OSStatus status = 0; status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 ); if( status < 0 ) { pathstripped = string_append( pathstripped, ".app" ); status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 ); } CFStringRef* args = 0; for( i = 0, size = array_size( proc->args ); i < size; ++i ) //App gets executable path automatically, don't include array_push( args, CFStringCreateWithCString( 0, proc->args[i], kCFStringEncodingUTF8 ) ); CFArrayRef argvref = CFArrayCreate( 0, (const void**)args, (CFIndex)array_size( args ), 0 ); params.flags = kLSLaunchDefaults; params.application = fsref; params.argv = argvref; log_debugf( 0, "Spawn process (LSOpenApplication): %s", pathstripped ); status = LSOpenApplication( ¶ms, &psn ); if( status != 0 ) { proc->code = status; log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process for executable '%s': %s", proc->path, system_error_message( status ) ); } CFRelease( argvref ); for( i = 0, size = array_size( args ); i < size; ++i ) CFRelease( args[i] ); memory_deallocate( fsref ); string_deallocate( pathstripped ); if( status == 0 ) { pid_t pid = 0; GetProcessPID( &psn, &pid ); proc->pid = pid; //Always "detached" with LSOpenApplication, not a child process at all //Setup a kqueue to watch when process terminates so we can emulate a wait proc->kq = kqueue(); if( proc->kq < 0 ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to create kqueue for process watch: %s (%d)", proc->kq, system_error_message( proc->kq ) ); proc->kq = 0; } else { struct kevent changes; EV_SET( &changes, (pid_t)pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, 0 ); int ret = kevent( proc->kq, &changes, 1, &changes, 1, 0 ); if( ret != 1 ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to setup kqueue for process watch, failed to add event to kqueue (%d)", ret ); close( proc->kq ); proc->kq = 0; } } } goto exit; } #endif #if FOUNDATION_PLATFORM_POSIX //Insert executable arg at start and null ptr at end int argc = array_size( proc->args ) + 1; array_grow( proc->args, 2 ); for( int arg = argc - 1; arg > 0; --arg ) proc->args[arg] = proc->args[arg-1]; proc->args[0] = string_clone( proc->path ); proc->args[argc] = 0; if( proc->flags & PROCESS_STDSTREAMS ) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); } proc->pid = 0; pid_t pid = fork(); if( pid == 0 ) { //Child if( string_length( proc->wd ) ) { log_debugf( 0, "Spawned child process, setting working directory to %s", proc->wd ); environment_set_current_working_directory( proc->wd ); } log_debugf( 0, "Child process executing: %s", proc->path ); if( proc->flags & PROCESS_STDSTREAMS ) { pipe_close_read( proc->pipeout ); dup2( pipe_write_fd( proc->pipeout ), STDOUT_FILENO ); pipe_close_write( proc->pipein ); dup2( pipe_read_fd( proc->pipein ), STDIN_FILENO ); } int code = execv( proc->path, proc->args ); if( code < 0 ) //Will always be true since this point will never be reached if execve() is successful log_warnf( 0, WARNING_BAD_DATA, "Child process failed execve() : %s : %s", proc->path, system_error_message( errno ) ); //Error process_exit( -1 ); } if( pid > 0 ) { log_debugf( 0, "Child process forked, pid %d", pid ); proc->pid = pid; if( proc->pipeout ) pipe_close_write( proc->pipeout ); if( proc->pipein ) pipe_close_read( proc->pipein ); if( proc->flags & PROCESS_DETACHED ) { int cstatus = 0; pid_t err = waitpid( pid, &cstatus, WNOHANG ); if( err == 0 ) { //TODO: Ugly wait to make sure process spawned correctly thread_sleep( 500 ); err = waitpid( pid, &cstatus, WNOHANG ); } if( err > 0 ) { //Process exited, check code proc->code = (int)((char)WEXITSTATUS( cstatus )); log_debugf( 0, "Child process returned: %d", proc->code ); return proc->code; } } } else { //Error proc->code = errno; log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process: %s : %s", proc->path, system_error_message( proc->code ) ); if( proc->pipeout ) stream_deallocate( proc->pipeout ); if( proc->pipein ) stream_deallocate( proc->pipein ); proc->pipeout = 0; proc->pipein = 0; return proc->code; } #endif #if !FOUNDATION_PLATFORM_WINDOWS && !FOUNDATION_PLATFORM_POSIX FOUNDATION_ASSERT_FAIL( "Process spawning not supported on platform" ); #endif #if FOUNDATION_PLATFORM_MACOSX exit: #endif if( proc->flags & PROCESS_DETACHED ) return PROCESS_STILL_ACTIVE; return process_wait( proc ); }
int process_spawn(process_t* proc) { static const string_const_t unescaped = { STRING_CONST("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.:/\\") }; size_t i, num_args; size_t size; #if FOUNDATION_PLATFORM_WINDOWS wchar_t* wcmdline; wchar_t* wwd; string_t cmdline; #endif #if !FOUNDATION_PLATFORM_POSIX size_t capacity; #endif proc->code = PROCESS_INVALID_ARGS; if (!proc->path.length) return proc->code; //Always escape path on Windows platforms #if FOUNDATION_PLATFORM_POSIX if (string_find_first_not_of(STRING_ARGS(proc->path), STRING_ARGS(unescaped), 0) != STRING_NPOS) #endif { bool preesc = (proc->path.str[0] != '"'); bool postesc = (proc->path.str[ proc->path.length - 1 ] != '"'); if (preesc || postesc) { char* buffer = memory_allocate(HASH_STRING, proc->path.length + 4, 0, MEMORY_PERSISTENT); string_t pathesc = string_concat_varg(buffer, proc->path.length + 4, "\"", (size_t)(preesc ? 1 : 0), STRING_ARGS(proc->path), "\"", (size_t)(postesc ? 1 : 0), nullptr); string_deallocate(proc->path.str); proc->path = pathesc; } } size = array_size(proc->args); for (i = 0, num_args = 0; i < size; ++i) { string_t arg = proc->args[i]; if (!arg.length) continue; ++num_args; #if !FOUNDATION_PLATFORM_POSIX if (string_find_first_not_of(arg.str, arg.length, unescaped.str, unescaped.length, 0) != STRING_NPOS) { if (arg.str[0] != '"') { //Check if we need to escape " characters string_t escarg; size_t pos = string_find(arg.str, arg.length, '"', 0); while (pos != STRING_NPOS) { if (arg.str[ pos - 1 ] != '\\') { string_const_t right = string_substr(STRING_ARGS(arg), 0, pos); string_const_t left = string_substr(STRING_ARGS(arg), pos, STRING_NPOS); capacity = arg.length + 2; escarg = string_allocate(0, capacity); escarg = string_concat(escarg.str, capacity, STRING_ARGS(right), STRING_CONST("\\")); escarg = string_append(STRING_ARGS(escarg), capacity, STRING_ARGS(left)); string_deallocate(arg.str); arg = escarg; } pos = string_find(STRING_ARGS(arg), '"', pos + 2); } escarg = string_allocate_concat_varg(STRING_CONST("\""), STRING_ARGS(arg), STRING_CONST("\""), nullptr); string_deallocate(arg.str); proc->args[i] = escarg; } } #endif } #if FOUNDATION_PLATFORM_WINDOWS # ifndef SEE_MASK_NOASYNC # define SEE_MASK_NOASYNC 0x00000100 # endif capacity = BUILD_MAX_PATHLEN; cmdline = string_allocate(0, capacity); //Don't prepend exe path to parameters if using ShellExecute if (!(proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE)) cmdline = string_copy(cmdline.str, capacity, STRING_ARGS(proc->path)); //Build command line string for (i = 0; i < size; ++i) { string_t arg = proc->args[i]; if (!arg.length) continue; if (cmdline.length + arg.length + 2 >= capacity) { string_t newline; capacity *= 2; newline = string_allocate(0, capacity); newline = string_copy(newline.str, capacity, STRING_ARGS(cmdline)); } if (cmdline.length) cmdline = string_append(STRING_ARGS(cmdline), capacity, STRING_CONST(" ")); cmdline = string_append(STRING_ARGS(cmdline), capacity, STRING_ARGS(arg)); } if (!proc->wd.length) proc->wd = string_clone(STRING_ARGS(environment_current_working_directory())); wcmdline = wstring_allocate_from_string(STRING_ARGS(cmdline)); wwd = wstring_allocate_from_string(STRING_ARGS(proc->wd)); if (proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE) { SHELLEXECUTEINFOW sei; wchar_t* wverb; wchar_t* wpath; wverb = (proc->verb.length ? wstring_allocate_from_string(STRING_ARGS(proc->verb)) : 0); wpath = wstring_allocate_from_string(STRING_ARGS(proc->path)); ZeroMemory(&sei, sizeof(sei)); sei.cbSize = sizeof(SHELLEXECUTEINFOW); sei.hwnd = 0; sei.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; sei.lpVerb = wverb; sei.lpFile = wpath; sei.lpParameters = wcmdline; sei.lpDirectory = wwd; sei.nShow = SW_SHOWNORMAL; if (!(proc->flags & PROCESS_CONSOLE)) sei.fMask |= SEE_MASK_NO_CONSOLE; if (proc->flags & PROCESS_STDSTREAMS) log_warn(0, WARNING_UNSUPPORTED, STRING_CONST("Unable to redirect standard in/out" " through pipes when using ShellExecute for process spawning")); log_debugf(0, STRING_CONST("Spawn process (ShellExecute): %.*s %.*s"), STRING_FORMAT(proc->path), STRING_FORMAT(cmdline)); if (!ShellExecuteExW(&sei)) { string_const_t errstr = system_error_message(0); log_warnf(0, WARNING_SYSTEM_CALL_FAIL, STRING_CONST("Unable to spawn process (ShellExecute) for executable '%.*s': %s"), STRING_FORMAT(proc->path), STRING_FORMAT(errstr)); } else { proc->hp = sei.hProcess; proc->ht = 0; proc->code = 0; } wstring_deallocate(wverb); wstring_deallocate(wpath); } else { STARTUPINFOW si; PROCESS_INFORMATION pi; BOOL inherit_handles = FALSE; memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); si.cb = sizeof(si); if (proc->flags & PROCESS_STDSTREAMS) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = pipe_write_handle(proc->pipeout); si.hStdInput = pipe_read_handle(proc->pipein); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); //Don't inherit wrong ends of pipes SetHandleInformation(pipe_read_handle(proc->pipeout), HANDLE_FLAG_INHERIT, 0); SetHandleInformation(pipe_write_handle(proc->pipein), HANDLE_FLAG_INHERIT, 0); inherit_handles = TRUE; } log_debugf(0, STRING_CONST("Spawn process (CreateProcess): %.*s %.*s"), STRING_FORMAT(proc->path), STRING_FORMAT(cmdline)); if (!CreateProcessW(0, wcmdline, 0, 0, inherit_handles, (proc->flags & PROCESS_CONSOLE) ? CREATE_NEW_CONSOLE : 0, 0, wwd, &si, &pi)) { string_const_t errstr = system_error_message(0); log_warnf(0, WARNING_SYSTEM_CALL_FAIL, STRING_CONST("Unable to spawn process (CreateProcess) for executable '%.*s': %.*s"), STRING_FORMAT(proc->path), STRING_FORMAT(errstr)); stream_deallocate(proc->pipeout); stream_deallocate(proc->pipein); proc->pipeout = 0; proc->pipein = 0; } else { proc->hp = pi.hProcess; proc->ht = pi.hThread; proc->code = 0; } if (proc->pipeout) pipe_close_write(proc->pipeout); if (proc->pipein) pipe_close_read(proc->pipein); } wstring_deallocate(wcmdline); wstring_deallocate(wwd); string_deallocate(cmdline.str); if (proc->code < 0) return proc->code; //Error #endif #if FOUNDATION_PLATFORM_MACOSX if (proc->flags & PROCESS_MACOSX_USE_OPENAPPLICATION) { proc->pid = 0; LSApplicationParameters params; ProcessSerialNumber psn; FSRef* fsref = memory_allocate(0, sizeof(FSRef), 0, MEMORY_TEMPORARY | MEMORY_ZERO_INITIALIZED); memset(¶ms, 0, sizeof(LSApplicationParameters)); memset(&psn, 0, sizeof(ProcessSerialNumber)); string_const_t pathstripped = string_strip(proc->path.str, proc->path.length, STRING_CONST("\"")); size_t localcap = pathstripped.length + 5; string_t localpath = string_allocate(0, localcap - 1); localpath = string_copy(localpath.str, localcap, STRING_ARGS(pathstripped)); //Need it zero terminated OSStatus status = 0; status = FSPathMakeRef((uint8_t*)localpath.str, fsref, 0); if (status < 0) { localpath = string_append(localpath.str, localpath.length, localcap, STRING_CONST(".app")); status = FSPathMakeRef((uint8_t*)localpath.str, fsref, 0); } CFStringRef* args = 0; for (i = 0, size = array_size(proc->args); i < size; ++i) //App gets executable path automatically, don't include array_push(args, CFStringCreateWithCString(0, proc->args[i].str, kCFStringEncodingUTF8)); CFArrayRef argvref = CFArrayCreate(0, (const void**)args, (CFIndex)array_size(args), 0); params.flags = kLSLaunchDefaults; params.application = fsref; params.argv = argvref; log_debugf(0, STRING_CONST("Spawn process (LSOpenApplication): %.*s"), STRING_FORMAT(localpath)); status = LSOpenApplication(¶ms, &psn); if (status != 0) { int err = status; string_const_t errmsg = system_error_message(err); proc->code = status; log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Unable to spawn process for executable '%.*s': %.*s (%d)"), STRING_FORMAT(localpath), STRING_FORMAT(errmsg), err); } CFRelease(argvref); for (i = 0, size = array_size(args); i < size; ++i) CFRelease(args[i]); array_deallocate(args); memory_deallocate(fsref); string_deallocate(localpath.str); if (status == 0) { pid_t pid = 0; GetProcessPID(&psn, &pid); proc->pid = pid; //Always "detached" with LSOpenApplication, not a child process at all //Setup a kqueue to watch when process terminates so we can emulate a wait proc->kq = kqueue(); if (proc->kq < 0) { string_const_t errmsg = system_error_message(proc->kq); log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Unable to create kqueue for process watch: %.*s (%d)"), STRING_FORMAT(errmsg), proc->kq); proc->kq = 0; } else { struct kevent changes; EV_SET(&changes, (pid_t)pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, 0); int ret = kevent(proc->kq, &changes, 1, &changes, 1, 0); if (ret != 1) { int err = errno; string_const_t errmsg = system_error_message(err); log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Unable to setup kqueue for process watch, failed to add event to kqueue: %.*s (%d)"), STRING_FORMAT(errmsg), err); close(proc->kq); proc->kq = 0; } } } goto exit; } #endif #if FOUNDATION_PLATFORM_POSIX //Insert executable arg at start and null ptr at end size_t arg; size_t argc = array_size(proc->args) + 1; array_grow(proc->args, 2); for (arg = argc - 1; arg > 0; --arg) proc->args[arg] = proc->args[arg - 1]; proc->args[0] = string_clone(STRING_ARGS(proc->path)); proc->args[argc] = (string_t) { 0, 0 }; char** argv = memory_allocate(0, sizeof(char*) * (argc + 1), 0, MEMORY_PERSISTENT); for (arg = 0; arg < argc; ++arg) argv[arg] = proc->args[arg].str; argv[argc] = 0; if (proc->flags & PROCESS_STDSTREAMS) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); } proc->pid = 0; pid_t pid = fork(); if (pid == 0) { //Child if (proc->wd.length) { log_debugf(0, STRING_CONST("Spawned child process, setting working directory to %.*s"), STRING_FORMAT(proc->wd)); environment_set_current_working_directory(STRING_ARGS(proc->wd)); } log_debugf(0, STRING_CONST("Child process executing: %.*s"), STRING_FORMAT(proc->path)); if (proc->flags & PROCESS_STDSTREAMS) { pipe_close_read(proc->pipeout); dup2(pipe_write_handle(proc->pipeout), STDOUT_FILENO); pipe_close_write(proc->pipein); dup2(pipe_read_handle(proc->pipein), STDIN_FILENO); } int code = execv(proc->path.str, (char* const*)argv); //Error int err = errno; string_const_t errmsg = system_error_message(err); log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Child process failed execve() '%.*s': %.*s (%d) (%d)"), STRING_FORMAT(proc->path), STRING_FORMAT(errmsg), err, code); process_exit(PROCESS_EXIT_FAILURE); FOUNDATION_UNUSED(code); } memory_deallocate(argv); if (pid > 0) { log_debugf(0, STRING_CONST("Child process forked, pid %d"), pid); proc->pid = pid; if (proc->pipeout) pipe_close_write(proc->pipeout); if (proc->pipein) pipe_close_read(proc->pipein); /*if (proc->flags & PROCESS_DETACHED) { int cstatus = 0; pid_t err = waitpid(pid, &cstatus, WNOHANG); if (err == 0) { //TODO: Ugly wait to make sure process spawned correctly thread_sleep(500); err = waitpid(pid, &cstatus, WNOHANG); } if (err > 0) { //Process exited, check code proc->pid = 0; proc->code = (int)((char)WEXITSTATUS(cstatus)); log_debugf(0, STRING_CONST("Child process returned: %d"), proc->code); return proc->code; } }*/ } else { //Error string_const_t errmsg; errmsg = system_error_message(proc->code); log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Unable to spawn process '%.*s': %.*s (%d)"), STRING_FORMAT(proc->path), STRING_FORMAT(errmsg), proc->code); if (proc->pipeout) stream_deallocate(proc->pipeout); if (proc->pipein) stream_deallocate(proc->pipein); proc->pipeout = 0; proc->pipein = 0; proc->code = PROCESS_INVALID_ARGS; return proc->code; } #endif #if !FOUNDATION_PLATFORM_WINDOWS && !FOUNDATION_PLATFORM_POSIX FOUNDATION_ASSERT_FAIL("Process spawning not supported on platform"); #endif #if FOUNDATION_PLATFORM_MACOSX exit: #endif if (proc->flags & PROCESS_DETACHED) return PROCESS_STILL_ACTIVE; return process_wait(proc); }
/** Check if a process with a given name is running * @param names list of names to filter on. All processes if empty list. * @return list of processname, process ID pairs. */ QMap<QString, QList<int> > Utils::findRunningProcess(QStringList names) { QMap<QString, QList<int> > processlist; QMap<QString, QList<int> > found; #if defined(Q_OS_WIN32) HANDLE hdl; PROCESSENTRY32 entry; bool result; hdl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hdl == INVALID_HANDLE_VALUE) { LOG_ERROR() << "CreateToolhelp32Snapshot failed."; return found; } entry.dwSize = sizeof(PROCESSENTRY32); entry.szExeFile[0] = '\0'; if(!Process32First(hdl, &entry)) { LOG_ERROR() << "Process32First failed."; return found; } do { int pid = entry.th32ProcessID; // FIXME: DWORD vs int! QString name = QString::fromWCharArray(entry.szExeFile); if(processlist.find(name) == processlist.end()) { processlist.insert(name, QList<int>()); } processlist[name].append(pid); entry.dwSize = sizeof(PROCESSENTRY32); entry.szExeFile[0] = '\0'; result = Process32Next(hdl, &entry); } while(result); CloseHandle(hdl); #endif #if defined(Q_OS_MACX) ProcessSerialNumber psn = { 0, kNoProcess }; OSErr err; do { pid_t pid; err = GetNextProcess(&psn); err = GetProcessPID(&psn, &pid); if(err == noErr) { char buf[32] = {0}; ProcessInfoRec info; memset(&info, 0, sizeof(ProcessInfoRec)); info.processName = (unsigned char*)buf; info.processInfoLength = sizeof(ProcessInfoRec); err = GetProcessInformation(&psn, &info); if(err == noErr) { // some processes start with nonprintable characters. Skip those. int i; for(i = 0; i < 32; i++) { if(isprint(buf[i])) break; } // avoid adding duplicates. QString name = QString::fromUtf8(&buf[i]); if(processlist.find(name) == processlist.end()) { processlist.insert(name, QList<int>()); } processlist[name].append(pid); } } } while(err == noErr); #endif #if defined(Q_OS_LINUX) // not implemented for Linux! #endif // Filter for names (unless empty) if(names.size() > 0) { for(int i = 0; i < names.size(); ++i) { QStringList k(processlist.keys()); #if defined(Q_OS_WIN32) // the process name might be truncated. Allow the extension to be partial. int index = k.indexOf(QRegExp(names.at(i) + "(\\.(e(x(e?)?)?)?)?", Qt::CaseInsensitive)); #else int index = k.indexOf(names.at(i)); #endif if(index != -1) { found.insert(k[index], processlist[k[index]]); } } } else { found = processlist; } LOG_INFO() << "Looking for processes" << names << "found" << found; return found; }
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; }