command-line install

code cleanup
This commit is contained in:
Patrick Wardle 2016-11-14 09:12:19 -10:00
parent c7aa22fda4
commit 579edd3435
11 changed files with 451 additions and 256 deletions

View File

@ -21,7 +21,7 @@
{
//return var
BOOL wasConfigured = NO;
//install
// ->starts on success
if(ACTION_INSTALL_FLAG == parameter)
@ -139,6 +139,9 @@ bail:
//path to login item
NSString* loginItem = nil;
//logged in user
NSString* user = nil;
//set src path
// ->orginally stored in installer app's /Resource bundle
appPathSrc = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:APP_NAME];
@ -169,9 +172,20 @@ bail:
//init path to login item
loginItem = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
//get user
user = loggedinUser();
if(nil == user)
{
//err msg
logMsg(LOG_ERR, @"failed to determine logged-in user");
//bail
goto bail;
}
//call into login item to install itself
// ->runs as non-root, so can access user's login items, etc
execTask(loginItem, @[ACTION_INSTALL]);
// ->runs as logged in user, so can access user's login items, etc
execTask(SUDO, @[@"-u", user, loginItem, ACTION_INSTALL]);
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"persisted %@", loginItem]);
@ -280,6 +294,9 @@ bail:
//path to login item
NSString* loginItem = nil;
//logged in user
NSString* user = nil;
//init path
appPath = [APPS_FOLDER stringByAppendingPathComponent:APP_NAME];
@ -287,13 +304,31 @@ bail:
//init path to login item
loginItem = [appPath stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
//call into login item to install itself
// ->runs as non-root, so can access user's login items, etc
execTask(loginItem, @[ACTION_UNINSTALL]);
//get user
user = loggedinUser();
if(nil == user)
{
//err msg
logMsg(LOG_ERR, @"failed to determine logged-in user");
//set flag
bAnyErrors = YES;
//keep uninstalling...
}
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"unpersisted %@", loginItem]);
//unistall login item
else
{
//call into login item to uninstall itself
// ->runs as logged in user, so can access user's login items, etc
execTask(SUDO, @[@"-u", user, loginItem, ACTION_UNINSTALL]);
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"unpersisted %@", loginItem]);
}
//delete folder
if(YES != [[NSFileManager defaultManager] removeItemAtPath:appPath error:&error])
{
@ -306,7 +341,6 @@ bail:
//keep uninstalling...
}
//only success when there were no errors
if(YES != bAnyErrors)
{

View File

@ -21,4 +21,10 @@
//spawn self as root
BOOL spawnAsRoot(const char* path2Self);
//install
BOOL cmdlineInstall();
//uninstall
BOOL cmdlineUninstall();
#endif /* main_h */

View File

@ -7,6 +7,8 @@
//
#import "main.h"
#import "Consts.h"
#import "Configure.h"
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[])
@ -16,38 +18,106 @@ int main(int argc, const char * argv[])
@autoreleasepool
{
//check for r00t
// ->then spawn self via auth exec
if(0 != geteuid())
{
//dbg msg
logMsg(LOG_DEBUG, @"non-root installer instance");
//spawn as root
if(YES != spawnAsRoot(argv[0]))
//handle '-install' / '-uninstall'
// ->this performs non-UI logic for easier automated deployment
if( (argc >= 2) &&
(YES != [[NSString stringWithUTF8String:argv[1]] hasPrefix:@"-psn_"]) )
{
//err msg
logMsg(LOG_ERR, @"failed to spawn self as r00t");
//first check rooot
if(0 != geteuid())
{
//err msg
printf("\nERROR: '%s' option, requires root\n\n", argv[1]);
//bail
goto bail;
}
//bail
goto bail;
}
//handle install
if(0 == strcmp(argv[1], CMD_INSTALL))
{
//install
if(YES != cmdlineInstall())
{
//err msg
printf("\nERROR: install failed\n\n");
//bail
goto bail;
}
//dbg msg
printf("OVERSIGHT: install ok!\n");
//happy
retVar = 0;
}
//handle uninstall
else if(0 == strcmp(argv[1], CMD_UNINSTALL))
{
//uninstall
if(YES != cmdlineUninstall())
{
//err msg
printf("\nERROR: install failed\n\n");
}
//dbg msg
printf("OVERSIGHT: uninstall ok!\n");
//happy
retVar = 0;
}
//invalid arg
else
{
//err msg
printf("\nERROR: '%s', is an invalid option\n\n", argv[1]);
//bail
goto bail;
}
}//args
//happy
retVar = 0;
}
//otherwise
// ->just kick off app, as we're root now
else
{
//dbg msg
logMsg(LOG_DEBUG, @"root installer instance");
//app away
retVar = NSApplicationMain(argc, (const char **)argv);
}
//no args
else
{
//check for r00t
// ->then spawn self via auth exec
if(0 != geteuid())
{
//dbg msg
logMsg(LOG_DEBUG, @"non-root installer instance");
//spawn as root
if(YES != spawnAsRoot(argv[0]))
{
//err msg
logMsg(LOG_ERR, @"failed to spawn self as r00t");
//bail
goto bail;
}
//happy
retVar = 0;
}
//otherwise
// ->just kick off app, as we're root now
else
{
//dbg msg
logMsg(LOG_DEBUG, @"root installer instance");
//app away
retVar = NSApplicationMain(argc, (const char **)argv);
}
}//no args
}//pool
@ -119,3 +189,18 @@ bail:
return bRet;
}
//install
BOOL cmdlineInstall()
{
//do it!
return [[[Configure alloc] init] configure:ACTION_INSTALL_FLAG];
}
//uninstall
BOOL cmdlineUninstall()
{
//do it!
return [[[Configure alloc] init] configure:ACTION_UNINSTALL_FLAG];
}

View File

@ -942,7 +942,7 @@ bail:
processName = getProcessName([event[EVENT_PROCESS_ID] intValue]);
//set other button title
notification.otherButtonTitle = @"allow";
notification.otherButtonTitle = @"allowz";
//set action title
notification.actionButtonTitle = @"block";
@ -1023,7 +1023,7 @@ bail:
}
//automatically invoked when user interacts w/ the notification popup
// ->only action we care about, is killing the process if they click 'block'
// ->handle rule creation, blocking/killing proc, etc
-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
//xpc connection
@ -1044,10 +1044,22 @@ bail:
//alloc log msg
sysLogMsg = [NSMutableString string];
//log event?
// ->but only allow/blocks (i.e. webcam activations)
if( (YES == [preferences[PREF_LOG_ACTIVITY] boolValue]) &&
(YES == [notification.actionButtonTitle isEqualToString:@"block"]) )
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"user responded to notification: %@", notification]);
//for alerts without an action
// ->don't need to do anything!
if(YES != notification.hasActionButton)
{
//dbg msg
logMsg(LOG_DEBUG, @"popup w/o an action, no need to do anything");
//bail
goto bail;
}
//log user's response?
if(YES == [preferences[PREF_LOG_ACTIVITY] boolValue])
{
//init msg
[sysLogMsg appendString:@"OVERSIGHT: "];
@ -1069,14 +1081,23 @@ bail:
syslog(LOG_ERR, "%s\n", sysLogMsg.UTF8String);
}
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"use responded to notification: %@", notification]);
//for video
// ->kill process if user clicked 'block'
if( (YES == [notification.actionButtonTitle isEqualToString:@"block"]) &&
(notification.activationType == NSUserNotificationActivationTypeActionButtonClicked))
//when user clicks 'allow'
// ->show popup w/ option to whitelist
if(notification.activationType == NSUserNotificationActivationTypeAdditionalActionClicked)
{
//TODO: show popup
//dbg msg
logMsg(LOG_DEBUG, @"user clicked 'allow'");
}
//when user clicks 'block'
// ->kill the process to block it
else if(notification.activationType == NSUserNotificationActivationTypeActionButtonClicked)
{
//dbg msg
logMsg(LOG_DEBUG, @"user clicked 'block'");
//extract process id
processID = notification.userInfo[EVENT_PROCESS_ID];
if(nil == processID)
@ -1087,7 +1108,7 @@ bail:
//bail
goto bail;
}
//alloc XPC connection
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
@ -1102,22 +1123,22 @@ bail:
//invoke XPC method 'killProcess' to terminate
[[xpcConnection remoteObjectProxy] killProcess:processID reply:^(BOOL wasKilled)
{
//check for err
if(YES != wasKilled)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to kill/block: %@", processID]);
}
//close connection
[xpcConnection invalidate];
//nil out
xpcConnection = nil;
}];
{
//check for err
if(YES != wasKilled)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to kill/block: %@", processID]);
}
//close connection
[xpcConnection invalidate];
//nil out
xpcConnection = nil;
}];
}//user clicked 'block'
//bail
@ -1126,7 +1147,6 @@ bail:
return;
}
//monitor for new procs (video only at the moment)
// ->runs until video is no longer in use (set elsewhere)
-(void)monitor4Procs

View File

@ -7,6 +7,7 @@
//
#import "main.h"
#import "Logging.h"
#import "Utilities.h"
//go go go
@ -17,38 +18,57 @@ int main(int argc, const char * argv[])
int iReturn = 0;
//dbg msg
logMsg(LOG_DEBUG, @"starting login item");
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"starting login item (args: %@/user: %@)", [[NSProcessInfo processInfo] arguments], NSUserName()]);
//check for uninstall/install flags
if(2 == argc)
{
//install
if(0 == strcmp(argv[1], ACTION_INSTALL.UTF8String))
{
//dbg msg
logMsg(LOG_DEBUG, @"running install logic");
//drop user privs
setuid(getuid());
//install
toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_INSTALL_FLAG);
//dbg msg
logMsg(LOG_DEBUG, @"installed login item");
//create default prefs
[@{PREF_LOG_ACTIVITY:@YES, PREF_START_AT_LOGIN:@YES, PREF_RUN_HEADLESS:@NO, PREF_CHECK_4_UPDATES:@YES} writeToFile:[APP_PREFERENCES stringByExpandingTildeInPath] atomically:NO];
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"created preferences at: %@", [APP_PREFERENCES stringByExpandingTildeInPath]]);
//bail
goto bail;
}
//uninstall
else if(0 == strcmp(argv[1], ACTION_UNINSTALL.UTF8String))
{
//dbg msg
logMsg(LOG_DEBUG, @"running uninstall logic");
//drop user privs
setuid(getuid());
//unistall
toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_UNINSTALL_FLAG);
//dbg msg
logMsg(LOG_DEBUG, @"removed login item");
//delete prefs
[[NSFileManager defaultManager] removeItemAtPath:[APP_PREFERENCES stringByExpandingTildeInPath] error:nil];
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"removed preferences from: %@", [APP_PREFERENCES stringByExpandingTildeInPath]]);
//bail
goto bail;
}

View File

@ -52,6 +52,18 @@
// ->for now, just cmd+q to quit app
[self registerKeypressHandler];
//create default prefs if there aren't any
// ->should only happen if new user runs the app
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[APP_PREFERENCES stringByExpandingTildeInPath]])
{
//dbg msg
logMsg(LOG_DEBUG, @"preference file not found; manually creating");
//write em out
// ->note; set 'start at login' to false, since no prefs here, mean installer wasn't run (user can later toggle)
[@{PREF_LOG_ACTIVITY:@YES, PREF_START_AT_LOGIN:@NO, PREF_RUN_HEADLESS:@NO, PREF_CHECK_4_UPDATES:@YES} writeToFile:[APP_PREFERENCES stringByExpandingTildeInPath] atomically:NO];
}
//start login item in background
// ->checks if already running though
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),

View File

@ -57,9 +57,6 @@
// ->ensures its only invoke while camera is not in use, so these are all just baselined procs
-(void)start;
//find 'VDCAssistant' or 'AppleCameraAssistant'
-(pid_t)findCameraAssistant;
//enumerate all (recent) process that appear to be using the mic
-(NSMutableArray*)enumAudioProcs;

View File

@ -75,174 +75,13 @@ static NSArray* ignoredProcs = nil;
return sharedEnumerator;
}
//find a process by name
-(pid_t)findProcess:(NSString*)processName
{
//pid
pid_t processID = 0;
//status
int status = -1;
//# of procs
int numberOfProcesses = 0;
//array of pids
pid_t* pids = NULL;
//process path
NSString* processPath = nil;
//get # of procs
numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
//alloc buffer for pids
pids = calloc(numberOfProcesses, sizeof(pid_t));
//get list of pids
status = proc_listpids(PROC_ALL_PIDS, 0, pids, numberOfProcesses * sizeof(pid_t));
if(status < 0)
{
//bail
goto bail;
}
//iterate over all pids
// ->get name for each via helper function
for(int i = 0; i < numberOfProcesses; ++i)
{
//skip blank pids
if(0 == pids[i])
{
//skip
continue;
}
//get name
processPath = getProcessPath(pids[i]);
if( (nil == processPath) ||
(0 == processPath.length) )
{
//skip
continue;
}
//match?
if(YES == [processPath isEqualToString:processName])
{
//save
processID = pids[i];
//pau
break;
}
}
//bail
bail:
//free buffer
if(NULL != pids)
{
//free
free(pids);
}
return processID;
}
//TODO: replace with [self findProcess]!!
//find 'VDCAssistant' or 'AppleCameraAssistant'
-(pid_t)findCameraAssistant
{
//pid of assistant
pid_t cameraAssistant = 0;
//status
int status = -1;
//# of procs
int numberOfProcesses = 0;
//array of pids
pid_t* pids = NULL;
//process path
NSString* processPath = nil;
//get # of procs
numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
//alloc buffer for pids
pids = calloc(numberOfProcesses, sizeof(pid_t));
//get list of pids
status = proc_listpids(PROC_ALL_PIDS, 0, pids, numberOfProcesses * sizeof(pid_t));
if(status < 0)
{
//bail
goto bail;
}
//iterate over all pids
// ->get name for each via helper function
for(int i = 0; i < numberOfProcesses; ++i)
{
//skip blank pids
if(0 == pids[i])
{
//skip
continue;
}
//get name
processPath = getProcessPath(pids[i]);
if( (nil == processPath) ||
(0 == processPath.length) )
{
//skip
continue;
}
//is 'VDCAssistant'?
if(YES == [processPath isEqualToString:VDC_ASSISTANT])
{
//save
cameraAssistant = pids[i];
//pau
break;
}
//is 'AppleCameraAssistant'?
else if(YES == [processPath isEqualToString:APPLE_CAMERA_ASSISTANT])
{
//save
cameraAssistant = pids[i];
//pau
break;
}
}
//bail
bail:
//free buffer
if(NULL != pids)
{
//free
free(pids);
}
return cameraAssistant;
}
//forever, baseline by getting all current procs that have sent a mach msg to *Assistant / coreaudio
// ->logic only exec'd while camera/mic is not in use, so these are all just baselined procs
-(void)start
{
//camera assistant
pid_t cameraAssistant = 0;
//baseline forever
// ->though logic will skip if video or mic is active (respectively)
while(YES)
@ -256,8 +95,27 @@ bail:
//dbg msg
logMsg(LOG_DEBUG, @"baselining mach senders for video...");
//find camera assistant
// ->first look for 'VDCAssistant'
cameraAssistant = findProcess(VDC_ASSISTANT);
if(0 == cameraAssistant)
{
//look for 'AppleCameraAssistant'
cameraAssistant = findProcess(APPLE_CAMERA_ASSISTANT);
}
//sanity check
if(0 == cameraAssistant)
{
//nap for a minute
[NSThread sleepForTimeInterval:60];
//next
continue;
}
//enumerate procs that have send mach messages
self.machSendersVideo = [self enumMachSenders:[self findCameraAssistant]];
self.machSendersVideo = [self enumMachSenders:cameraAssistant];
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersVideo.count, self.machSendersVideo]);
@ -270,7 +128,7 @@ bail:
logMsg(LOG_DEBUG, @"baselining mach senders for audio...");
//enumerate procs that have send mach messages
self.machSendersAudio = [self enumMachSenders:[self findProcess:CORE_AUDIO]];
self.machSendersAudio = [self enumMachSenders:findProcess(CORE_AUDIO)];
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersAudio.count, self.machSendersVideo]);
@ -317,8 +175,15 @@ bail:
@synchronized(self)
{
//find 'VDCAssistant' or 'AppleCameraAssistant'
cameraAssistant = [self findCameraAssistant];
//first look for 'VDCAssistant'
cameraAssistant = findProcess(VDC_ASSISTANT);
if(0 == cameraAssistant)
{
//look for 'AppleCameraAssistant'
cameraAssistant = findProcess(APPLE_CAMERA_ASSISTANT);
}
//sanity check
if(0 == cameraAssistant)
{
//err msg
@ -327,7 +192,7 @@ bail:
//bail
goto bail;
}
//get procs that currrently have sent Mach msg to *Assistant
// ->returns dictionary of process id, and number of mach messages
currentSenders = [self enumMachSenders:cameraAssistant];
@ -414,7 +279,7 @@ bail:
@synchronized(self)
{
//find coreaudio
coreAudio = [self findProcess:CORE_AUDIO];
coreAudio = findProcess(CORE_AUDIO);
if(0 == coreAudio)
{
//err msg
@ -803,7 +668,7 @@ bail:
}
//sampling a process creates a temp file
//->delete it!
//->make sure we delete it this file to clean up ;)
[self deleteSampleFile:processPath];
//for now, just check for 'CMIOGraph::DoWork'
@ -885,6 +750,9 @@ bail:
// ->extra logic is executed to 'refresh' iVars when video is disabled
-(void)updateVideoStatus:(BOOL)isEnabled
{
//camera assistant
pid_t cameraAssistant = 0;
//sync
@synchronized(self)
{
@ -895,10 +763,32 @@ bail:
// ->re-enumerate mach senders
if(YES != isEnabled)
{
//first, look for 'VDCAssistant'
cameraAssistant = findProcess(VDC_ASSISTANT);
if(0 == cameraAssistant)
{
//look for 'AppleCameraAssistant'
cameraAssistant = findProcess(APPLE_CAMERA_ASSISTANT);
}
//sanity check
if(0 == cameraAssistant)
{
//err msg
logMsg(LOG_ERR, @"failed to find VDCAssistant/AppleCameraAssistant process");
//bail
goto bail;
}
//enumerate mach senders
self.machSendersVideo = [self enumMachSenders:[self findCameraAssistant]];
self.machSendersVideo = [self enumMachSenders:cameraAssistant];
}
}
}//sync
//bail
bail:
return;
}
@ -918,7 +808,7 @@ bail:
if(YES != isEnabled)
{
//enumerate mach senders
self.machSendersAudio = [self enumMachSenders:[self findProcess:CORE_AUDIO]];
self.machSendersAudio = [self enumMachSenders:findProcess(CORE_AUDIO)];
//enumerate i/o registry user clients
self.userClients = [self enumDomainUserClients];

View File

@ -36,6 +36,12 @@
//OS minor version el capitan
#define OS_MINOR_VERSION_EL_CAPITAN 11
//install flag
#define CMD_INSTALL "-install"
//uninstall flag
#define CMD_UNINSTALL "-uninstall"
//action to install
// ->also button title
#define ACTION_INSTALL @"Install"
@ -92,8 +98,13 @@
//path to xattr
#define XATTR @"/usr/bin/xattr"
//path to sudo
#define SUDO @"/usr/bin/sudo"
//path to facetime
#define FACE_TIME @"/Applications/FaceTime.app/Contents/MacOS/FaceTime"
#endif

View File

@ -67,4 +67,10 @@ void makeModal(NSWindowController* windowController);
// ->either add (install) or remove (uninstall)
BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag);
//get logged in user
NSString* loggedinUser();
//find a process by name
pid_t findProcess(NSString* processName);
#endif

View File

@ -20,6 +20,7 @@
#import <CommonCrypto/CommonDigest.h>
#import <SystemConfiguration/SystemConfiguration.h>
//get OS version
NSDictionary* getOSVersion()
{
@ -295,6 +296,9 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments)
//set task's output
[task setStandardOutput:outPipe];
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"@exec'ing %@ (args: %@)", binaryPath, arguments]);
//wrap task launch
@try
{
@ -727,7 +731,7 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
{
//flag
BOOL wasToggled = NO;
//login item ref
LSSharedFileListRef loginItemsRef = NULL;
@ -765,11 +769,14 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
else
{
//err msg
logMsg(LOG_ERR, @"failed to added login item");
logMsg(LOG_ERR, @"failed to add login item");
//bail
goto bail;
}
//happy
wasToggled = YES;
}
//remove (uninstall)
else
@ -797,6 +804,9 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
{
//remove
LSSharedFileListItemRemove(loginItemsRef, (__bridge LSSharedFileListItemRef)item);
//happy
wasToggled = YES;
}
//release
@ -813,9 +823,6 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
}//remove/uninstall
//happy
wasToggled = YES;
//bail
bail:
@ -842,7 +849,114 @@ bail:
return wasToggled;
}
//get logged in user
NSString* loggedinUser()
{
//store
SCDynamicStoreRef store = nil;
//user
NSString* user = nil;
//create store
store = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
if(NULL == store)
{
//bail
goto bail;
}
//get user
user = CFBridgingRelease(SCDynamicStoreCopyConsoleUser(store, NULL, NULL));
//bail
bail:
//release store
if(NULL != store)
{
//release
CFRelease(store);
}
return user;
}
//find a process by name
pid_t findProcess(NSString* processName)
{
//pid
pid_t processID = 0;
//status
int status = -1;
//# of procs
int numberOfProcesses = 0;
//array of pids
pid_t* pids = NULL;
//process path
NSString* processPath = nil;
//get # of procs
numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
//alloc buffer for pids
pids = calloc(numberOfProcesses, sizeof(pid_t));
//get list of pids
status = proc_listpids(PROC_ALL_PIDS, 0, pids, numberOfProcesses * sizeof(pid_t));
if(status < 0)
{
//bail
goto bail;
}
//iterate over all pids
// ->get name for each via helper function
for(int i = 0; i < numberOfProcesses; ++i)
{
//skip blank pids
if(0 == pids[i])
{
//skip
continue;
}
//get name
processPath = getProcessPath(pids[i]);
if( (nil == processPath) ||
(0 == processPath.length) )
{
//skip
continue;
}
//match?
if(YES == [processPath isEqualToString:processName])
{
//save
processID = pids[i];
//pau
break;
}
}//all procs
//bail
bail:
//free buffer
if(NULL != pids)
{
//free
free(pids);
}
return processID;
}