コード例 #1
0
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;
}
コード例 #2
0
ファイル: Overlay.cpp プロジェクト: Acidburn0zzz/mumble
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;
			}
		}
	}
}
コード例 #3
0
pid_t HelperMacX::getKeepassxPID(){
	if (0 == keepassxPID) {
		ProcessSerialNumber processSerialNumber;
		GetCurrentProcess(&processSerialNumber);
		GetProcessPID(&processSerialNumber, &keepassxPID);
	}
	return keepassxPID;
}
コード例 #4
0
ファイル: main.c プロジェクト: dane-harnett/workspace
static AXUIElementRef getFrontMostApp ()
{
    pid_t pid;
    ProcessSerialNumber psn;

    GetFrontProcess(&psn);
    GetProcessPID(&psn, &pid);
    return AXUIElementCreateApplication(pid);
}
コード例 #5
0
ファイル: mac_saver_module.cpp プロジェクト: DanAurea/boinc
// 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;
}
コード例 #6
0
ファイル: axlib.c プロジェクト: KenSong/pyatom
pid_t
getFrontmostPID(void)
{
   pid_t pid;
   ProcessSerialNumber psn;

   GetFrontProcess(&psn);
   GetProcessPID(&psn, &pid);

   return pid;
}
コード例 #7
0
ファイル: carbon.cpp プロジェクト: josephnoir/kwm
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);
    });
コード例 #8
0
ファイル: PostInstall.cpp プロジェクト: freehal/boinc-freehal
// 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;
}
コード例 #9
0
ファイル: main.c プロジェクト: randombrad/liferay-nativity
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;
        
    }
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: ar.c プロジェクト: DanielGit/Intrisit8000
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;
}
コード例 #12
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);
}
コード例 #13
0
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;
}
コード例 #14
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;
}
コード例 #15
0
ファイル: main.c プロジェクト: viqsoft/liferay-nativity
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;
	}
}
コード例 #16
0
ファイル: main.c プロジェクト: eliego/scrocht
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;
}
コード例 #17
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;
}
コード例 #18
0
ファイル: utils.cpp プロジェクト: ifroz/rockbox
/** 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;
}
コード例 #19
0
ファイル: PostInstall.cpp プロジェクト: freehal/boinc-freehal
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;
}
コード例 #20
0
ファイル: process.c プロジェクト: Jasper-Bekkers/ProDBG
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( &params, 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( &params, &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 );
}
コード例 #21
0
ファイル: process.c プロジェクト: haifenghuang/foundation_lib
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(&params, 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(&params, &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);
}
コード例 #22
0
ファイル: utils.cpp プロジェクト: Rockbox/rockbox
/** 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;
}
コード例 #23
0
ファイル: PostInstall.cpp プロジェクト: freehal/boinc-freehal
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;
}