v 1.2.0
high sierra compatibility improved nstask execution alleviated need for 'sudo' refactored code to find camera/mic process pushed various XPC intensive stuff into background
This commit is contained in:
parent
027d0840ed
commit
d7b4648a90
|
@ -172,7 +172,7 @@
|
||||||
7D24C85D1D2CDEA7009932EE /* Project object */ = {
|
7D24C85D1D2CDEA7009932EE /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0800;
|
LastUpgradeCheck = 0900;
|
||||||
ORGANIZATIONNAME = "Objective-See";
|
ORGANIZATIONNAME = "Objective-See";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
7D24C8641D2CDEA7009932EE = {
|
7D24C8641D2CDEA7009932EE = {
|
||||||
|
@ -229,7 +229,7 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "#for normal builds\n# ->just copy in app\n#cp -R -f $BUILT_PRODUCTS_DIR/OverSight.app $BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/\n\n#for achieving\n# ->first build OverSight in release mode (don't archive it)\n# then archive (this) installer app\ncp -R -f ~/objective-see/OverSight/DerivedData/OverSight/Build/Products/Release/OverSight.app ~/objective-see/OverSight/DerivedData/OverSight/Build/Intermediates/ArchiveIntermediates/Installer/BuildProductsPath/Release/OverSight_Installer.app/Contents/Resources/\n";
|
shellScript = "#for normal builds\n# ->just copy in app\n#cp -R -f $BUILT_PRODUCTS_DIR/OverSight.app $BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/\n\n#for achieving\n# ->first build OverSight in release mode (don't archive it)\n# then archive (this) installer app\n#cp -R -f ~/objective-see/OverSight/DerivedData/OverSight/Build/Products/Release/OverSight.app ~/objective-see/OverSight/DerivedData/OverSight/Build/Intermediates/ArchiveIntermediates/Installer/BuildProductsPath/Release/OverSight_Installer.app/Contents/Resources/\n";
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
@ -273,14 +273,20 @@
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
@ -319,14 +325,20 @@
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
|
|
@ -72,6 +72,9 @@ bail:
|
||||||
//alloc/init
|
//alloc/init
|
||||||
configureWindowController = [[ConfigureWindowController alloc] initWithWindowNibName:@"ConfigureWindowController"];
|
configureWindowController = [[ConfigureWindowController alloc] initWithWindowNibName:@"ConfigureWindowController"];
|
||||||
|
|
||||||
|
//indicated title bar is tranparent (too)
|
||||||
|
self.configureWindowController.window.titlebarAppearsTransparent = YES;
|
||||||
|
|
||||||
//display it
|
//display it
|
||||||
// ->call this first to so that outlets are connected
|
// ->call this first to so that outlets are connected
|
||||||
[self.configureWindowController display];
|
[self.configureWindowController display];
|
||||||
|
|
|
@ -117,7 +117,6 @@
|
||||||
//no errors
|
//no errors
|
||||||
wasConfigured = YES;
|
wasConfigured = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return wasConfigured;
|
return wasConfigured;
|
||||||
|
@ -154,8 +153,8 @@ bail:
|
||||||
//path to login item
|
//path to login item
|
||||||
NSString* loginItem = nil;
|
NSString* loginItem = nil;
|
||||||
|
|
||||||
//logged in user
|
//logged in user info
|
||||||
NSString* user = nil;
|
NSMutableDictionary* userInfo = nil;
|
||||||
|
|
||||||
//white list
|
//white list
|
||||||
NSString* whiteList = nil;
|
NSString* whiteList = nil;
|
||||||
|
@ -184,7 +183,7 @@ bail:
|
||||||
|
|
||||||
//remove xattrs
|
//remove xattrs
|
||||||
// ->otherwise app translocation causes issues
|
// ->otherwise app translocation causes issues
|
||||||
execTask(XATTR, @[@"-cr", appPathDest], YES);
|
execTask(XATTR, @[@"-cr", appPathDest], NO);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -194,9 +193,9 @@ bail:
|
||||||
//init path to login item
|
//init path to login item
|
||||||
loginItem = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
loginItem = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
||||||
|
|
||||||
//get user
|
//get user info
|
||||||
user = loggedinUser();
|
userInfo = loggedinUser();
|
||||||
if(nil == user)
|
if(nil == userInfo[@"user"])
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
||||||
|
@ -206,7 +205,7 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//create app support directory
|
//create app support directory
|
||||||
if(YES != [self createAppSupport:user])
|
if(YES != [self createAppSupport:userInfo[@"user"]])
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to create app support directory for current user");
|
logMsg(LOG_ERR, @"failed to create app support directory for current user");
|
||||||
|
@ -221,7 +220,7 @@ bail:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//init path to whitelist
|
//init path to whitelist
|
||||||
whiteList = [[NSString pathWithComponents:@[@"/Users/", user, APP_SUPPORT_DIRECTORY]] stringByAppendingPathComponent:FILE_WHITELIST];
|
whiteList = [[NSString pathWithComponents:@[@"/Users/", userInfo[@"user"], APP_SUPPORT_DIRECTORY]] stringByAppendingPathComponent:FILE_WHITELIST];
|
||||||
|
|
||||||
//if whitelist exists
|
//if whitelist exists
|
||||||
// ->make sure it's owned by root
|
// ->make sure it's owned by root
|
||||||
|
@ -232,8 +231,7 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//call into login item to install itself
|
//call into login item to install itself
|
||||||
// ->runs as logged in user, so can access user's login items, etc
|
execTask(loginItem, @[[NSString stringWithUTF8String:CMD_INSTALL]], NO);
|
||||||
execTask(SUDO, @[@"-u", user, loginItem, [NSString stringWithUTF8String:CMD_INSTALL]], YES);
|
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -266,7 +264,6 @@ bail:
|
||||||
//no error
|
//no error
|
||||||
wasInstalled = YES;
|
wasInstalled = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return wasInstalled;
|
return wasInstalled;
|
||||||
|
@ -279,34 +276,19 @@ bail:
|
||||||
//flag
|
//flag
|
||||||
BOOL bStarted = NO;
|
BOOL bStarted = NO;
|
||||||
|
|
||||||
//logged in user
|
|
||||||
NSString* user = nil;
|
|
||||||
|
|
||||||
//path to login item
|
//path to login item
|
||||||
NSString* loginItem = nil;
|
NSString* loginItem = nil;
|
||||||
|
|
||||||
//get user
|
|
||||||
user = loggedinUser();
|
|
||||||
if(nil == user)
|
|
||||||
{
|
|
||||||
//err msg
|
|
||||||
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
|
||||||
|
|
||||||
//bail
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
//init path
|
//init path
|
||||||
loginItem = [[APPS_FOLDER stringByAppendingPathComponent:APP_NAME] stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
loginItem = [[APPS_FOLDER stringByAppendingPathComponent:APP_NAME] stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
||||||
|
|
||||||
//start it!
|
//start it!
|
||||||
// ->don't wait, as it won't exit
|
// ->don't wait, as it won't exit
|
||||||
execTask(SUDO, @[@"-u", user, loginItem], NO);
|
execTask(loginItem, nil, NO);
|
||||||
|
|
||||||
//happy
|
//happy
|
||||||
bStarted = YES;
|
bStarted = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return bStarted;
|
return bStarted;
|
||||||
|
@ -350,8 +332,8 @@ bail:
|
||||||
//error
|
//error
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
|
|
||||||
//logged in user
|
//logged in user info
|
||||||
NSString* user = nil;
|
NSMutableDictionary* userInfo = nil;
|
||||||
|
|
||||||
//uninstall command
|
//uninstall command
|
||||||
// ->changed between v1.0 and 1.1+
|
// ->changed between v1.0 and 1.1+
|
||||||
|
@ -385,8 +367,8 @@ bail:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//get user
|
//get user
|
||||||
user = loggedinUser();
|
userInfo = loggedinUser();
|
||||||
if(nil == user)
|
if(nil == userInfo[@"user"])
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
||||||
|
@ -401,8 +383,7 @@ bail:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//call into login item to uninstall itself
|
//call into login item to uninstall itself
|
||||||
// ->runs as logged in user, so can access user's login items, etc
|
execTask(loginItem, @[uninstallCmd], YES);
|
||||||
execTask(SUDO, @[@"-u", user, loginItem, uninstallCmd], YES);
|
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -436,13 +417,13 @@ bail:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//delete app's app support folder
|
//delete app's app support folder
|
||||||
if(YES == [[NSFileManager defaultManager] fileExistsAtPath:[self appSupportPath:user]])
|
if(YES == [[NSFileManager defaultManager] fileExistsAtPath:[self appSupportPath:userInfo[@"user"]]])
|
||||||
{
|
{
|
||||||
//delete
|
//delete
|
||||||
if(YES != [self removeAppSupport:user])
|
if(YES != [self removeAppSupport:userInfo[@"user"]])
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete app support directory %@", [self appSupportPath:user]]);
|
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete app support directory %@", [self appSupportPath:userInfo[@"user"]]]);
|
||||||
|
|
||||||
//set flag
|
//set flag
|
||||||
bAnyErrors = YES;
|
bAnyErrors = YES;
|
||||||
|
@ -455,7 +436,7 @@ bail:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"removed app support directory %@", [self appSupportPath:user]]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"removed app support directory %@", [self appSupportPath:userInfo[@"user"]]]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -469,7 +450,6 @@ bail:
|
||||||
wasUninstalled = YES;
|
wasUninstalled = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return wasUninstalled;
|
return wasUninstalled;
|
||||||
|
@ -531,7 +511,6 @@ bail:
|
||||||
//happy
|
//happy
|
||||||
createdDirectory = YES;
|
createdDirectory = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return createdDirectory;
|
return createdDirectory;
|
||||||
|
@ -580,12 +559,9 @@ bail:
|
||||||
//happy
|
//happy
|
||||||
removedDirectory = YES;
|
removedDirectory = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return removedDirectory;
|
return removedDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,9 @@
|
||||||
// ->center, make front, set bg to white, etc
|
// ->center, make front, set bg to white, etc
|
||||||
-(void)display
|
-(void)display
|
||||||
{
|
{
|
||||||
|
//indicated title bar is tranparent (too)
|
||||||
|
self.window.titlebarAppearsTransparent = YES;
|
||||||
|
|
||||||
//center window
|
//center window
|
||||||
[[self window] center];
|
[[self window] center];
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
BOOL spawnAsRoot(const char* path2Self);
|
BOOL spawnAsRoot(const char* path2Self);
|
||||||
|
|
||||||
//install
|
//install
|
||||||
BOOL cmdlineInstall();
|
BOOL cmdlineInstall(void);
|
||||||
|
|
||||||
//uninstall
|
//uninstall
|
||||||
BOOL cmdlineUninstall();
|
BOOL cmdlineUninstall(void);
|
||||||
|
|
||||||
#endif /* main_h */
|
#endif /* main_h */
|
||||||
|
|
147
Installer/main.m
147
Installer/main.m
|
@ -17,101 +17,102 @@ int main(int argc, const char * argv[])
|
||||||
//return var
|
//return var
|
||||||
int retVar = -1;
|
int retVar = -1;
|
||||||
|
|
||||||
@autoreleasepool
|
//pool
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
//handle '-install' / '-uninstall'
|
||||||
|
// ->this performs non-UI logic for easier automated deployment
|
||||||
|
if( (argc >= 2) &&
|
||||||
|
( (0 == strcmp(argv[1], CMD_INSTALL)) || (0 == strcmp(argv[1], CMD_UNINSTALL)) ) )
|
||||||
{
|
{
|
||||||
//handle '-install' / '-uninstall'
|
//first check rooot
|
||||||
// ->this performs non-UI logic for easier automated deployment
|
if(0 != geteuid())
|
||||||
if( (argc >= 2) &&
|
|
||||||
( (0 == strcmp(argv[1], CMD_INSTALL)) || (0 == strcmp(argv[1], CMD_UNINSTALL)) ) )
|
|
||||||
{
|
{
|
||||||
//first check rooot
|
//err msg
|
||||||
if(0 != geteuid())
|
printf("\nERROR: '%s' option, requires root\n\n", argv[1]);
|
||||||
{
|
|
||||||
//err msg
|
|
||||||
printf("\nERROR: '%s' option, requires root\n\n", argv[1]);
|
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
}//args
|
//handle install
|
||||||
|
if(0 == strcmp(argv[1], CMD_INSTALL))
|
||||||
//check for r00t
|
|
||||||
// ->then spawn self via auth exec
|
|
||||||
if(0 != geteuid())
|
|
||||||
{
|
{
|
||||||
//dbg msg
|
//install
|
||||||
#ifdef DEBUG
|
if(YES != cmdlineInstall())
|
||||||
logMsg(LOG_DEBUG, @"non-root installer instance");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//spawn as root
|
|
||||||
if(YES != spawnAsRoot(argv[0]))
|
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to spawn self as r00t");
|
printf("\nERROR: install failed\n\n");
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
printf("OVERSIGHT: install ok!\n");
|
||||||
|
|
||||||
//happy
|
//happy
|
||||||
retVar = 0;
|
retVar = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise
|
//handle uninstall
|
||||||
// ->just kick off app, as we're root now
|
else if(0 == strcmp(argv[1], CMD_UNINSTALL))
|
||||||
else
|
|
||||||
{
|
{
|
||||||
//dbg msg
|
//uninstall
|
||||||
#ifdef DEBUG
|
if(YES != cmdlineUninstall())
|
||||||
logMsg(LOG_DEBUG, @"root installer instance");
|
{
|
||||||
#endif
|
//err msg
|
||||||
|
printf("\nERROR: install failed\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
//app away
|
//dbg msg
|
||||||
retVar = NSApplicationMain(argc, (const char **)argv);
|
printf("OVERSIGHT: uninstall ok!\n");
|
||||||
|
|
||||||
|
//happy
|
||||||
|
retVar = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
|
||||||
|
}//args
|
||||||
|
|
||||||
|
//check for r00t
|
||||||
|
// ->then spawn self via auth exec
|
||||||
|
if(0 != geteuid())
|
||||||
|
{
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"non-root installer instance");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//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
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"root installer instance");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//app away
|
||||||
|
retVar = NSApplicationMain(argc, (const char **)argv);
|
||||||
|
}
|
||||||
|
|
||||||
}//pool
|
}//pool
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
|
|
|
@ -415,8 +415,6 @@ bail:
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bRet;
|
return bRet;
|
||||||
|
@ -474,7 +472,7 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//helper function
|
//helper function
|
||||||
// ->determines if video went active/inactive then invokes notification generator method
|
// determines if video went active/inactive then invokes notification generator method
|
||||||
-(void)handleVideoNotification:(CMIOObjectID)deviceID addresses:(const CMIOObjectPropertyAddress[]) addresses
|
-(void)handleVideoNotification:(CMIOObjectID)deviceID addresses:(const CMIOObjectPropertyAddress[]) addresses
|
||||||
{
|
{
|
||||||
//event dictionary
|
//event dictionary
|
||||||
|
@ -517,9 +515,14 @@ bail:
|
||||||
[devices addObject:@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)}];
|
[devices addObject:@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)}];
|
||||||
}
|
}
|
||||||
|
|
||||||
//send msg to status menu
|
//update status menu
|
||||||
// ->update menu to show (all) devices & their status
|
// run on main thread, since its a UI update
|
||||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:devices];
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//update status menu
|
||||||
|
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:devices];
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
//add timestamp
|
//add timestamp
|
||||||
event[EVENT_TIMESTAMP] = [NSDate date];
|
event[EVENT_TIMESTAMP] = [NSDate date];
|
||||||
|
@ -579,9 +582,6 @@ bail:
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"video procs from XPC: %@", videoProcesses]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"video procs from XPC: %@", videoProcesses]);
|
||||||
|
@ -594,7 +594,14 @@ bail:
|
||||||
event[EVENT_PROCESS_ID] = processID;
|
event[EVENT_PROCESS_ID] = processID;
|
||||||
|
|
||||||
//generate notification
|
//generate notification
|
||||||
[self generateNotification:event];
|
// do on main thread since its a UI event
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//generate notification
|
||||||
|
[self generateNotification:event];
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if no consumer process was found
|
//if no consumer process was found
|
||||||
|
@ -605,7 +612,13 @@ bail:
|
||||||
event[EVENT_PROCESS_ID] = @0;
|
event[EVENT_PROCESS_ID] = @0;
|
||||||
|
|
||||||
//generate notification
|
//generate notification
|
||||||
[self generateNotification:event];
|
// do on main thread since its a UI event
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//generate notification
|
||||||
|
[self generateNotification:event];
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//signal sema
|
//signal sema
|
||||||
|
@ -625,11 +638,15 @@ bail:
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
//generate notification
|
//generate notification
|
||||||
[self generateNotification:event];
|
// do on main thread since its a UI event
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//generate notification
|
||||||
|
[self generateNotification:event];
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//poll for new video procs
|
//poll for new video procs
|
||||||
|
@ -694,8 +711,27 @@ bail:
|
||||||
// ->invoked when video changes & just calls helper function
|
// ->invoked when video changes & just calls helper function
|
||||||
CMIOObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const CMIOObjectPropertyAddress addresses[])
|
CMIOObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const CMIOObjectPropertyAddress addresses[])
|
||||||
{
|
{
|
||||||
//invoke helper function
|
//on main thread?
|
||||||
[self handleVideoNotification:deviceID addresses:addresses];
|
// handle on background thread
|
||||||
|
if(YES == [NSThread isMainThread])
|
||||||
|
{
|
||||||
|
//invoke in background
|
||||||
|
// XPC stuff might be slow!
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||||
|
^{
|
||||||
|
|
||||||
|
//handle notification
|
||||||
|
[self handleVideoNotification:deviceID addresses:addresses];
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//on background thread
|
||||||
|
// just can invoke as it
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//handle notification
|
||||||
|
[self handleVideoNotification:deviceID addresses:addresses];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//register (add) property block listener
|
//register (add) property block listener
|
||||||
|
@ -764,6 +800,9 @@ bail:
|
||||||
//event dictionary
|
//event dictionary
|
||||||
NSMutableDictionary* event = nil;
|
NSMutableDictionary* event = nil;
|
||||||
|
|
||||||
|
//devices
|
||||||
|
NSMutableArray* devices = nil;
|
||||||
|
|
||||||
//xpc connection
|
//xpc connection
|
||||||
__block NSXPCConnection* xpcConnection = nil;
|
__block NSXPCConnection* xpcConnection = nil;
|
||||||
|
|
||||||
|
@ -773,6 +812,9 @@ bail:
|
||||||
//init dictionary
|
//init dictionary
|
||||||
event = [NSMutableDictionary dictionary];
|
event = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
//init array for devices
|
||||||
|
devices = [NSMutableArray array];
|
||||||
|
|
||||||
//sync
|
//sync
|
||||||
@synchronized (self)
|
@synchronized (self)
|
||||||
{
|
{
|
||||||
|
@ -781,9 +823,28 @@ bail:
|
||||||
// ->updates 'audioActive' iVar
|
// ->updates 'audioActive' iVar
|
||||||
[self setAudioDevStatus:deviceID];
|
[self setAudioDevStatus:deviceID];
|
||||||
|
|
||||||
//send msg to status menu
|
//add camera
|
||||||
// ->update menu to show (all) devices & their status
|
if(nil != self.camera)
|
||||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:@[@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)},@{EVENT_DEVICE:self.camera, EVENT_DEVICE_STATUS:@(self.videoActive)}]];
|
{
|
||||||
|
//add
|
||||||
|
[devices addObject:@{EVENT_DEVICE:self.camera, EVENT_DEVICE_STATUS:@(self.videoActive)}];
|
||||||
|
}
|
||||||
|
|
||||||
|
//add mic
|
||||||
|
if(nil != self.mic)
|
||||||
|
{
|
||||||
|
//add
|
||||||
|
[devices addObject:@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)}];
|
||||||
|
}
|
||||||
|
|
||||||
|
//update status menu
|
||||||
|
// run on main thread, since its a UI update
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//update status menu
|
||||||
|
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:devices];
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
//add timestamp
|
//add timestamp
|
||||||
event[EVENT_TIMESTAMP] = [NSDate date];
|
event[EVENT_TIMESTAMP] = [NSDate date];
|
||||||
|
@ -824,8 +885,8 @@ bail:
|
||||||
// ->XPC reply block will signal semaphore
|
// ->XPC reply block will signal semaphore
|
||||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
//if video just started
|
//if audio just started
|
||||||
// ->ask for video procs from XPC
|
// ->ask for audio procs from XPC
|
||||||
if(YES == self.audioActive)
|
if(YES == self.audioActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
@ -843,9 +904,6 @@ bail:
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"audio procs from XPC: %@", audioProcesses]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"audio procs from XPC: %@", audioProcesses]);
|
||||||
|
@ -858,7 +916,13 @@ bail:
|
||||||
event[EVENT_PROCESS_ID] = processID;
|
event[EVENT_PROCESS_ID] = processID;
|
||||||
|
|
||||||
//generate notification
|
//generate notification
|
||||||
[self generateNotification:event];
|
// do on main thread since its a UI event
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//generate notification
|
||||||
|
[self generateNotification:event];
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//if no consumer process was found
|
//if no consumer process was found
|
||||||
|
@ -869,7 +933,13 @@ bail:
|
||||||
event[EVENT_PROCESS_ID] = @0;
|
event[EVENT_PROCESS_ID] = @0;
|
||||||
|
|
||||||
//generate notification
|
//generate notification
|
||||||
[self generateNotification:event];
|
// do on main thread since its a UI event
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//generate notification
|
||||||
|
[self generateNotification:event];
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//signal sema
|
//signal sema
|
||||||
|
@ -889,11 +959,14 @@ bail:
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
//generate notification
|
//generate notification
|
||||||
[self generateNotification:event];
|
// do on main thread since its a UI event
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//generate notification
|
||||||
|
[self generateNotification:event];
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}//sync
|
}//sync
|
||||||
|
@ -930,7 +1003,27 @@ bail:
|
||||||
// ->invoked when audio changes & just calls helper function
|
// ->invoked when audio changes & just calls helper function
|
||||||
AudioObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses)
|
AudioObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses)
|
||||||
{
|
{
|
||||||
[self handleAudioNotification:deviceID];
|
//on main thread?
|
||||||
|
// handle on background thread
|
||||||
|
if(YES == [NSThread isMainThread])
|
||||||
|
{
|
||||||
|
//invoke in background
|
||||||
|
// XPC stuff might be slow!
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||||
|
^{
|
||||||
|
|
||||||
|
//handle notification
|
||||||
|
[self handleAudioNotification:deviceID];
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//on background thread
|
||||||
|
// just can invoke as it
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//handle notification
|
||||||
|
[self handleAudioNotification:deviceID];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//add property listener for audio changes
|
//add property listener for audio changes
|
||||||
|
@ -957,6 +1050,9 @@ bail:
|
||||||
// ->handles extra logic like ignore whitelisted apps, disable alerts (if user has turned that off), etc
|
// ->handles extra logic like ignore whitelisted apps, disable alerts (if user has turned that off), etc
|
||||||
-(void)generateNotification:(NSMutableDictionary*)event
|
-(void)generateNotification:(NSMutableDictionary*)event
|
||||||
{
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
//notification
|
//notification
|
||||||
NSUserNotification* notification = nil;
|
NSUserNotification* notification = nil;
|
||||||
|
|
||||||
|
@ -1291,6 +1387,8 @@ bail:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
@ -1307,6 +1405,9 @@ bail:
|
||||||
// ->handle rule creation, blocking/killing proc, etc
|
// ->handle rule creation, blocking/killing proc, etc
|
||||||
-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
|
-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
|
||||||
{
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
//xpc connection
|
//xpc connection
|
||||||
__block NSXPCConnection* xpcConnection = nil;
|
__block NSXPCConnection* xpcConnection = nil;
|
||||||
|
|
||||||
|
@ -1524,12 +1625,12 @@ bail:
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}//user clicked 'block'
|
}//user clicked 'block'
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
@ -1607,9 +1708,13 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//monitor for new procs (video only at the moment)
|
//monitor for new procs (video only at the moment)
|
||||||
// ->runs until video is no longer in use (set elsewhere)
|
// runs until video is no longer in use (set elsewhere)
|
||||||
-(void)monitor4Procs
|
-(void)monitor4Procs
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
//xpc connection
|
//xpc connection
|
||||||
NSXPCConnection* xpcConnection = nil;
|
NSXPCConnection* xpcConnection = nil;
|
||||||
|
|
||||||
|
@ -1621,22 +1726,12 @@ bail:
|
||||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] video is active, so polling for new procs");
|
logMsg(LOG_DEBUG, @"[MONITOR THREAD] video is active, so polling for new procs");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//alloc XPC connection
|
|
||||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
|
||||||
|
|
||||||
//set remote object interface
|
|
||||||
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
|
||||||
|
|
||||||
//set classes
|
|
||||||
// ->arrays/numbers ok to vend
|
|
||||||
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
|
||||||
forSelector: @selector(getVideoProcs:reply:) argumentIndex: 0 ofReply: YES];
|
|
||||||
//resume
|
|
||||||
[xpcConnection resume];
|
|
||||||
|
|
||||||
//poll while video is active
|
//poll while video is active
|
||||||
while(YES == self.videoActive)
|
while(YES == self.videoActive)
|
||||||
{
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
//init wait semaphore
|
//init wait semaphore
|
||||||
waitSema = dispatch_semaphore_create(0);
|
waitSema = dispatch_semaphore_create(0);
|
||||||
|
|
||||||
|
@ -1645,6 +1740,20 @@ bail:
|
||||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] (re)Asking XPC for (new) video procs");
|
logMsg(LOG_DEBUG, @"[MONITOR THREAD] (re)Asking XPC for (new) video procs");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//alloc XPC connection
|
||||||
|
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||||
|
|
||||||
|
//set remote object interface
|
||||||
|
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||||
|
|
||||||
|
//set classes
|
||||||
|
// ->arrays/numbers ok to vend
|
||||||
|
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
||||||
|
forSelector: @selector(getVideoProcs:reply:) argumentIndex: 0 ofReply: YES];
|
||||||
|
//resume
|
||||||
|
[xpcConnection resume];
|
||||||
|
|
||||||
|
|
||||||
//invoke XPC service to get (new) video procs
|
//invoke XPC service to get (new) video procs
|
||||||
// ->will generate user notifications for any new processes
|
// ->will generate user notifications for any new processes
|
||||||
[[xpcConnection remoteObjectProxy] getVideoProcs:YES reply:^(NSMutableArray* videoProcesses)
|
[[xpcConnection remoteObjectProxy] getVideoProcs:YES reply:^(NSMutableArray* videoProcesses)
|
||||||
|
@ -1652,7 +1761,7 @@ bail:
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"[MONITOR THREAD] found %lu new video procs: %@", (unsigned long)videoProcesses.count, videoProcesses]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"[MONITOR THREAD] found %lu new video procs: %@", (unsigned long)videoProcesses.count, videoProcesses]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//generate a notification for each process
|
//generate a notification for each process
|
||||||
// ->double check video is still active though...
|
// ->double check video is still active though...
|
||||||
|
@ -1672,26 +1781,27 @@ bail:
|
||||||
//signal sema
|
//signal sema
|
||||||
dispatch_semaphore_signal(waitSema);
|
dispatch_semaphore_signal(waitSema);
|
||||||
|
|
||||||
|
//invalidate
|
||||||
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
//wait until XPC is done
|
//wait until XPC is done
|
||||||
// ->XPC reply block will signal semaphore
|
// ->XPC reply block will signal semaphore
|
||||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
//nap
|
//nap
|
||||||
[NSThread sleepForTimeInterval:5.0f];
|
[NSThread sleepForTimeInterval:5.0f];
|
||||||
|
|
||||||
}//run until video (camera) is off
|
}//run until video (camera) is off
|
||||||
|
|
||||||
//bail
|
//pool
|
||||||
|
}
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
//close connection
|
|
||||||
[xpcConnection invalidate];
|
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] exiting polling/monitor thread since camera is off");
|
logMsg(LOG_DEBUG, @"[MONITOR THREAD] exiting polling/monitor thread since camera is off");
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#import "Logging.h"
|
#import "Logging.h"
|
||||||
#import "Utilities.h"
|
#import "Utilities.h"
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
#import "XPCProtocol.h"
|
||||||
|
|
||||||
@interface AppDelegate ()
|
@interface AppDelegate ()
|
||||||
|
|
||||||
|
@ -29,16 +30,30 @@
|
||||||
//preferences
|
//preferences
|
||||||
NSDictionary* preferences = nil;
|
NSDictionary* preferences = nil;
|
||||||
|
|
||||||
|
//logged in user info
|
||||||
|
NSMutableDictionary* userInfo = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"starting login item app logic");
|
logMsg(LOG_DEBUG, @"starting login item app logic");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//get user
|
||||||
|
userInfo = loggedinUser();
|
||||||
|
if(nil == userInfo[@"user"])
|
||||||
|
{
|
||||||
|
//err msg
|
||||||
|
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
//drop group privs
|
//drop group privs
|
||||||
setgid(getgid());
|
setgid([userInfo[@"gid"] intValue]);
|
||||||
|
|
||||||
//drop user privs
|
//drop user privs
|
||||||
setuid(getuid());
|
setuid([userInfo[@"uid"] intValue]);
|
||||||
|
|
||||||
//load preferences
|
//load preferences
|
||||||
preferences = [NSDictionary dictionaryWithContentsOfFile:[APP_PREFERENCES stringByExpandingTildeInPath]];
|
preferences = [NSDictionary dictionaryWithContentsOfFile:[APP_PREFERENCES stringByExpandingTildeInPath]];
|
||||||
|
@ -99,10 +114,12 @@
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
// ->and to file
|
// ->and to file
|
||||||
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging intialized");
|
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging intialized (login item)");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//spawn 'heartbeat' thread to XPC to keep it open
|
||||||
|
[NSThread detachNewThreadSelector:@selector(heartBeat) toTarget:self withObject:nil];
|
||||||
|
|
||||||
//create/init av event monitor
|
//create/init av event monitor
|
||||||
avMonitor = [[AVMonitor alloc] init];
|
avMonitor = [[AVMonitor alloc] init];
|
||||||
|
|
||||||
|
@ -194,6 +211,60 @@ bail:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ping XPC service to keep it alive
|
||||||
|
-(void)heartBeat
|
||||||
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
//xpc connection
|
||||||
|
__block NSXPCConnection* xpcConnection = nil;
|
||||||
|
|
||||||
|
//wait semaphore
|
||||||
|
dispatch_semaphore_t waitSema = nil;
|
||||||
|
|
||||||
|
//alloc XPC connection
|
||||||
|
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||||
|
|
||||||
|
//set remote object interface
|
||||||
|
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||||
|
|
||||||
|
//resume
|
||||||
|
[xpcConnection resume];
|
||||||
|
|
||||||
|
//forever
|
||||||
|
while(YES)
|
||||||
|
{
|
||||||
|
//init wait semaphore
|
||||||
|
waitSema = dispatch_semaphore_create(0);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
//dbg msg
|
||||||
|
logMsg(LOG_DEBUG, @"sending XPC heart beat request");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//XPC service to begin baselining mach messages
|
||||||
|
// ->wait, since want this to compelete before doing other things!
|
||||||
|
[[xpcConnection remoteObjectProxy] heartBeat:^(BOOL reply)
|
||||||
|
{
|
||||||
|
//signal sema
|
||||||
|
dispatch_semaphore_signal(waitSema);
|
||||||
|
|
||||||
|
}];
|
||||||
|
|
||||||
|
//wait until XPC is done
|
||||||
|
// ->XPC reply block will signal semaphore
|
||||||
|
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
|
//nap
|
||||||
|
[NSThread sleepForTimeInterval:3.0f];
|
||||||
|
}
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//going bye-bye
|
//going bye-bye
|
||||||
// ->close logging
|
// ->close logging
|
||||||
-(void)applicationWillTerminate:(NSNotification *)notification
|
-(void)applicationWillTerminate:(NSNotification *)notification
|
||||||
|
@ -202,7 +273,7 @@ bail:
|
||||||
logMsg(LOG_DEBUG|LOG_TO_FILE, @"OverSight ending");
|
logMsg(LOG_DEBUG|LOG_TO_FILE, @"OverSight ending");
|
||||||
|
|
||||||
//log msg
|
//log msg
|
||||||
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging deinitialized");
|
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging deinitialized (login item)");
|
||||||
|
|
||||||
//stop logz
|
//stop logz
|
||||||
deinitLogging();
|
deinitLogging();
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>LSUIElement</key>
|
<key>LSUIElement</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
//version label/string
|
//version label/string
|
||||||
@property (weak) IBOutlet NSTextField *windowText;
|
@property (weak) IBOutlet NSTextField *windowText;
|
||||||
|
|
||||||
|
|
||||||
/* METHODS */
|
/* METHODS */
|
||||||
|
|
||||||
//save stuff into iVars
|
//save stuff into iVars
|
||||||
|
|
|
@ -137,9 +137,6 @@
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,10 @@
|
||||||
//create/update status item menu
|
//create/update status item menu
|
||||||
-(void)updateStatusItemMenu:(NSArray*)devices
|
-(void)updateStatusItemMenu:(NSArray*)devices
|
||||||
{
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//menu
|
//menu
|
||||||
NSMenu* menu = nil;
|
NSMenu* menu = nil;
|
||||||
|
|
||||||
|
@ -194,6 +198,8 @@
|
||||||
//tie menu to status item
|
//tie menu to status item
|
||||||
self.statusItem.menu = menu;
|
self.statusItem.menu = menu;
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,44 @@ int main(int argc, const char * argv[])
|
||||||
//return var
|
//return var
|
||||||
int iReturn = 0;
|
int iReturn = 0;
|
||||||
|
|
||||||
|
//logged in user info
|
||||||
|
NSMutableDictionary* userInfo = nil;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"starting login item (args: %@/user: %@)", [[NSProcessInfo processInfo] arguments], NSUserName()]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"starting login item (args: %@/user: %@/%@)", [[NSProcessInfo processInfo] arguments], NSUserName(), loggedinUser()]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//check for uninstall/install flags, and process to remove from whitelist
|
//check for uninstall/install flags, and process to remove from whitelist
|
||||||
if(2 == argc)
|
if(2 == argc)
|
||||||
{
|
{
|
||||||
|
//drops privs when installing/uninstalling
|
||||||
|
// do here, only for these as they then bail
|
||||||
|
if( (0 == strcmp(argv[1], CMD_INSTALL)) ||
|
||||||
|
(0 == strcmp(argv[1], CMD_UNINSTALL)) )
|
||||||
|
{
|
||||||
|
//get user
|
||||||
|
userInfo = loggedinUser();
|
||||||
|
if(nil == userInfo[@"user"])
|
||||||
|
{
|
||||||
|
//err msg
|
||||||
|
logMsg(LOG_ERR, @"failed to determine logged-in user");
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
//drop group privs
|
||||||
|
setgid([userInfo[@"gid"] intValue]);
|
||||||
|
|
||||||
|
//drop user privs
|
||||||
|
setuid([userInfo[@"uid"] intValue]);
|
||||||
|
}
|
||||||
|
|
||||||
//install
|
//install
|
||||||
if(0 == strcmp(argv[1], CMD_INSTALL))
|
if(0 == strcmp(argv[1], CMD_INSTALL))
|
||||||
{
|
{
|
||||||
|
@ -34,9 +64,6 @@ int main(int argc, const char * argv[])
|
||||||
logMsg(LOG_DEBUG, @"running install logic");
|
logMsg(LOG_DEBUG, @"running install logic");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//drop user privs
|
|
||||||
setuid(getuid());
|
|
||||||
|
|
||||||
//install
|
//install
|
||||||
if(YES != toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_INSTALL_FLAG))
|
if(YES != toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_INSTALL_FLAG))
|
||||||
{
|
{
|
||||||
|
@ -74,9 +101,6 @@ int main(int argc, const char * argv[])
|
||||||
logMsg(LOG_DEBUG, @"running uninstall logic");
|
logMsg(LOG_DEBUG, @"running uninstall logic");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//drop user privs
|
|
||||||
setuid(getuid());
|
|
||||||
|
|
||||||
//uninstall
|
//uninstall
|
||||||
if(YES != toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_UNINSTALL_FLAG))
|
if(YES != toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_UNINSTALL_FLAG))
|
||||||
{
|
{
|
||||||
|
@ -130,7 +154,8 @@ int main(int argc, const char * argv[])
|
||||||
//launch app normally
|
//launch app normally
|
||||||
iReturn = NSApplicationMain(argc, argv);
|
iReturn = NSApplicationMain(argc, argv);
|
||||||
|
|
||||||
//bail
|
}//pool
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return iReturn;
|
return iReturn;
|
||||||
|
@ -174,9 +199,6 @@ void unWhiteList(NSString* process, NSNumber* device)
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
|
||||||
xpcConnection = nil;
|
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -244,7 +244,7 @@ bail:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//log msg
|
//log msg
|
||||||
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging initialized");
|
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging initialized (main app)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//when logging is disabled
|
//when logging is disabled
|
||||||
|
@ -252,7 +252,7 @@ bail:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//log msg
|
//log msg
|
||||||
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging deinitialized");
|
logMsg(LOG_DEBUG|LOG_TO_FILE, @"logging deinitialized (main app)");
|
||||||
|
|
||||||
//close
|
//close
|
||||||
deinitLogging();
|
deinitLogging();
|
||||||
|
@ -539,7 +539,6 @@ bail:
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||||
<key>LSUIElement</key>
|
<key>LSUIElement</key>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
|
||||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||||
<rect key="contentRect" x="196" y="240" width="611" height="270"/>
|
<rect key="contentRect" x="196" y="240" width="611" height="270"/>
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
|
||||||
<value key="minSize" type="size" width="500" height="100"/>
|
<value key="minSize" type="size" width="500" height="100"/>
|
||||||
<value key="maxSize" type="size" width="1500" height="500"/>
|
<value key="maxSize" type="size" width="1500" height="500"/>
|
||||||
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
|
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
|
||||||
|
|
|
@ -413,7 +413,7 @@
|
||||||
8B57559319DA3E9500799E6B /* Project object */ = {
|
8B57559319DA3E9500799E6B /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0820;
|
LastUpgradeCheck = 0900;
|
||||||
ORGANIZATIONNAME = "Cory Bohon";
|
ORGANIZATIONNAME = "Cory Bohon";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
7DC9C8111D641A350017D143 = {
|
7DC9C8111D641A350017D143 = {
|
||||||
|
@ -620,14 +620,20 @@
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
@ -667,14 +673,20 @@
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
|
|
@ -33,6 +33,12 @@
|
||||||
|
|
||||||
/* PROPERTIES */
|
/* PROPERTIES */
|
||||||
|
|
||||||
|
//camera assistant pid
|
||||||
|
@property pid_t cameraAssistantProcess;
|
||||||
|
|
||||||
|
//core audio pid
|
||||||
|
@property pid_t coreAudioProcess;
|
||||||
|
|
||||||
//flag indicating video is active
|
//flag indicating video is active
|
||||||
@property BOOL videoActive;
|
@property BOOL videoActive;
|
||||||
|
|
||||||
|
@ -49,8 +55,6 @@
|
||||||
// ->IOService:/AppleACPIPlatformExpert/IOPMrootDomain/RootDomainUserClient
|
// ->IOService:/AppleACPIPlatformExpert/IOPMrootDomain/RootDomainUserClient
|
||||||
@property(nonatomic, retain)NSMutableDictionary* userClients;
|
@property(nonatomic, retain)NSMutableDictionary* userClients;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* METHODS */
|
/* METHODS */
|
||||||
|
|
||||||
//singleton interface
|
//singleton interface
|
||||||
|
|
|
@ -23,8 +23,11 @@ static NSArray* ignoredProcs = nil;
|
||||||
@synthesize audioActive;
|
@synthesize audioActive;
|
||||||
@synthesize userClients;
|
@synthesize userClients;
|
||||||
@synthesize videoActive;
|
@synthesize videoActive;
|
||||||
|
@synthesize coreAudioProcess;
|
||||||
@synthesize machSendersAudio;
|
@synthesize machSendersAudio;
|
||||||
@synthesize machSendersVideo;
|
@synthesize machSendersVideo;
|
||||||
|
@synthesize cameraAssistantProcess;
|
||||||
|
|
||||||
|
|
||||||
//init
|
//init
|
||||||
-(instancetype)init
|
-(instancetype)init
|
||||||
|
@ -78,13 +81,28 @@ static NSArray* ignoredProcs = nil;
|
||||||
// ->logic only exec'd while camera/mic is not in use, so these are all just baselined procs
|
// ->logic only exec'd while camera/mic is not in use, so these are all just baselined procs
|
||||||
-(void)start
|
-(void)start
|
||||||
{
|
{
|
||||||
//camera assistant
|
//flag
|
||||||
pid_t cameraAssistant = 0;
|
BOOL nap = NO;
|
||||||
|
|
||||||
//baseline forever
|
//baseline forever
|
||||||
// ->though logic will skip if video or mic is active (respectively)
|
// ->though logic will skip if video or mic is active (respectively)
|
||||||
while(YES)
|
while(YES)
|
||||||
{
|
{
|
||||||
|
//le sleep?
|
||||||
|
if(nap == YES)
|
||||||
|
{
|
||||||
|
//nap
|
||||||
|
[NSThread sleepForTimeInterval:30];
|
||||||
|
}
|
||||||
|
|
||||||
|
//set flag
|
||||||
|
// from now on, want to wait a bit
|
||||||
|
nap = YES;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//sync baselining
|
//sync baselining
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
|
@ -97,31 +115,36 @@ static NSArray* ignoredProcs = nil;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//find camera assistant
|
//find camera assistant
|
||||||
// ->first look for 'VDCAssistant'
|
// only do this once, or again, if it died
|
||||||
cameraAssistant = findProcess(VDC_ASSISTANT);
|
if( (0 == self.cameraAssistantProcess) ||
|
||||||
if(0 == cameraAssistant)
|
(YES != isProcessAlive(self.cameraAssistantProcess)) )
|
||||||
{
|
{
|
||||||
//look for 'AppleCameraAssistant'
|
//find camera assistant
|
||||||
cameraAssistant = findProcess(APPLE_CAMERA_ASSISTANT);
|
// ->first look for 'VDCAssistant'
|
||||||
|
self.cameraAssistantProcess = findProcess(VDC_ASSISTANT);
|
||||||
|
if(0 == self.cameraAssistantProcess)
|
||||||
|
{
|
||||||
|
//look for 'AppleCameraAssistant'
|
||||||
|
self.cameraAssistantProcess = findProcess(APPLE_CAMERA_ASSISTANT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//sanity check
|
//baseline
|
||||||
if(0 == cameraAssistant)
|
if(0 != self.cameraAssistantProcess)
|
||||||
{
|
{
|
||||||
//nap for a minute
|
//dbg msg
|
||||||
[NSThread sleepForTimeInterval:60];
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"camera assistent process: %d", self.coreAudioProcess]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//next
|
//enumerate procs that have send mach messages
|
||||||
continue;
|
self.machSendersVideo = [self enumMachSenders:self.cameraAssistantProcess];
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersVideo.count, self.machSendersVideo]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//enumerate procs that have send mach messages
|
|
||||||
self.machSendersVideo = [self enumMachSenders:cameraAssistant];
|
|
||||||
|
|
||||||
//dbg msg
|
|
||||||
#ifdef DEBUG
|
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersVideo.count, self.machSendersVideo]);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//only baseline if audio isn't active
|
//only baseline if audio isn't active
|
||||||
|
@ -132,29 +155,47 @@ static NSArray* ignoredProcs = nil;
|
||||||
logMsg(LOG_DEBUG, @"baselining mach senders for audio...");
|
logMsg(LOG_DEBUG, @"baselining mach senders for audio...");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//enumerate procs that have send mach messages
|
//find core audio
|
||||||
self.machSendersAudio = [self enumMachSenders:findProcess(CORE_AUDIO)];
|
// only do this once, or again, if it died
|
||||||
|
if( (0 == self.coreAudioProcess) ||
|
||||||
|
(YES != isProcessAlive(self.coreAudioProcess)) )
|
||||||
|
{
|
||||||
|
//find core audio
|
||||||
|
self.coreAudioProcess = findProcess(CORE_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
//dbg msg
|
//baseline
|
||||||
#ifdef DEBUG
|
if(0 != self.coreAudioProcess)
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersAudio.count, self.machSendersVideo]);
|
{
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"camera core audio process: %d", self.coreAudioProcess]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//dbg msg
|
//enumerate procs that have send mach messages
|
||||||
logMsg(LOG_DEBUG, @"baselining i/o registry entries for audio...");
|
self.machSendersAudio = [self enumMachSenders:self.coreAudioProcess];
|
||||||
#endif
|
|
||||||
|
|
||||||
//enumerate procs that have i/o registry entries
|
//dbg msg
|
||||||
self.userClients = [self enumDomainUserClients];
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersAudio.count, self.machSendersVideo]);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
logMsg(LOG_DEBUG, @"baselining i/o registry entries for audio...");
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined i/or registry senders: %@", (unsigned long)self.userClients.count, self.userClients]);
|
#endif
|
||||||
#endif
|
|
||||||
|
//enumerate procs that have i/o registry entries
|
||||||
|
self.userClients = [self enumDomainUserClients];
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined i/or registry senders: %@", (unsigned long)self.userClients.count, self.userClients]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//nap for a minute
|
}//sync
|
||||||
[NSThread sleepForTimeInterval:60];
|
|
||||||
|
}//pool
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -166,6 +207,10 @@ static NSArray* ignoredProcs = nil;
|
||||||
//current procs
|
//current procs
|
||||||
NSMutableArray* videoProcs = nil;
|
NSMutableArray* videoProcs = nil;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//mach senders
|
//mach senders
|
||||||
NSMutableDictionary* currentSenders = nil;
|
NSMutableDictionary* currentSenders = nil;
|
||||||
|
|
||||||
|
@ -173,11 +218,8 @@ static NSArray* ignoredProcs = nil;
|
||||||
// ->those that have new mach message
|
// ->those that have new mach message
|
||||||
NSMutableArray* candidateVideoProcs = nil;
|
NSMutableArray* candidateVideoProcs = nil;
|
||||||
|
|
||||||
//pid of camera assistant process
|
//foreground app
|
||||||
pid_t cameraAssistant = 0;
|
pid_t activeApp = 0;
|
||||||
|
|
||||||
//'frontmost' application
|
|
||||||
pid_t activeApp = -1;
|
|
||||||
|
|
||||||
//alloc
|
//alloc
|
||||||
candidateVideoProcs = [NSMutableArray array];
|
candidateVideoProcs = [NSMutableArray array];
|
||||||
|
@ -187,16 +229,23 @@ static NSArray* ignoredProcs = nil;
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
|
|
||||||
//first look for 'VDCAssistant'
|
//find camera assistant
|
||||||
cameraAssistant = findProcess(VDC_ASSISTANT);
|
// only do this once, or again, if it died
|
||||||
if(0 == cameraAssistant)
|
if( (0 == self.cameraAssistantProcess) ||
|
||||||
|
(YES != isProcessAlive(self.cameraAssistantProcess)) )
|
||||||
{
|
{
|
||||||
//look for 'AppleCameraAssistant'
|
//find camera assistant
|
||||||
cameraAssistant = findProcess(APPLE_CAMERA_ASSISTANT);
|
// ->first look for 'VDCAssistant'
|
||||||
|
self.cameraAssistantProcess = findProcess(VDC_ASSISTANT);
|
||||||
|
if(0 == self.cameraAssistantProcess)
|
||||||
|
{
|
||||||
|
//look for 'AppleCameraAssistant'
|
||||||
|
self.cameraAssistantProcess = findProcess(APPLE_CAMERA_ASSISTANT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//sanity check
|
//sanity check
|
||||||
if(0 == cameraAssistant)
|
if(0 == self.cameraAssistantProcess)
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to find VDCAssistant/AppleCameraAssistant process");
|
logMsg(LOG_ERR, @"failed to find VDCAssistant/AppleCameraAssistant process");
|
||||||
|
@ -207,7 +256,7 @@ static NSArray* ignoredProcs = nil;
|
||||||
|
|
||||||
//get procs that currrently have sent Mach msg to *Assistant
|
//get procs that currrently have sent Mach msg to *Assistant
|
||||||
// ->returns dictionary of process id, and number of mach messages
|
// ->returns dictionary of process id, and number of mach messages
|
||||||
currentSenders = [self enumMachSenders:cameraAssistant];
|
currentSenders = [self enumMachSenders:self.cameraAssistantProcess];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -219,7 +268,7 @@ static NSArray* ignoredProcs = nil;
|
||||||
{
|
{
|
||||||
//add any candidate procs
|
//add any candidate procs
|
||||||
// ->those that have new mach message
|
// ->those that have new mach message
|
||||||
if( [currentSenders[processID] intValue] > [self.machSendersVideo[processID] intValue])
|
if([currentSenders[processID] intValue] > [self.machSendersVideo[processID] intValue])
|
||||||
{
|
{
|
||||||
//ignore client/requestor
|
//ignore client/requestor
|
||||||
if(clientPID == processID.intValue)
|
if(clientPID == processID.intValue)
|
||||||
|
@ -271,7 +320,8 @@ static NSArray* ignoredProcs = nil;
|
||||||
|
|
||||||
}//sync
|
}//sync
|
||||||
|
|
||||||
//bail
|
}//pool
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return videoProcs;
|
return videoProcs;
|
||||||
|
@ -283,6 +333,10 @@ bail:
|
||||||
//current procs
|
//current procs
|
||||||
NSMutableArray* audioProcs = nil;
|
NSMutableArray* audioProcs = nil;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//current mach senders
|
//current mach senders
|
||||||
NSMutableDictionary* currentSenders = nil;
|
NSMutableDictionary* currentSenders = nil;
|
||||||
|
|
||||||
|
@ -302,9 +356,6 @@ bail:
|
||||||
//itersection set
|
//itersection set
|
||||||
NSMutableSet* intersection = nil;
|
NSMutableSet* intersection = nil;
|
||||||
|
|
||||||
//pid of coreaudio process
|
|
||||||
pid_t coreAudio = 0;
|
|
||||||
|
|
||||||
//'frontmost' application
|
//'frontmost' application
|
||||||
pid_t activeApp = -1;
|
pid_t activeApp = -1;
|
||||||
|
|
||||||
|
@ -314,16 +365,22 @@ bail:
|
||||||
//alloc array
|
//alloc array
|
||||||
newUserClients = [NSMutableArray array];
|
newUserClients = [NSMutableArray array];
|
||||||
|
|
||||||
//alloc array
|
|
||||||
candidateAudioProcs = [NSMutableArray array];
|
|
||||||
|
|
||||||
//sync this logic
|
//sync this logic
|
||||||
// ->prevent baselining thread from doing anything
|
// ->prevent baselining thread from doing anything
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
//find coreaudio
|
//find coreaudio
|
||||||
coreAudio = findProcess(CORE_AUDIO);
|
//find core audio
|
||||||
if(0 == coreAudio)
|
// only do this once, or again, if it died
|
||||||
|
if( (0 == self.coreAudioProcess) ||
|
||||||
|
(YES != isProcessAlive(self.coreAudioProcess)) )
|
||||||
|
{
|
||||||
|
//find core audio
|
||||||
|
self.coreAudioProcess = findProcess(CORE_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sanity check
|
||||||
|
if(0 == self.coreAudioProcess)
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to find coreaudio process");
|
logMsg(LOG_ERR, @"failed to find coreaudio process");
|
||||||
|
@ -334,7 +391,7 @@ bail:
|
||||||
|
|
||||||
//get procs that currrently have sent Mach msg to core audio
|
//get procs that currrently have sent Mach msg to core audio
|
||||||
// ->returns dictionary of process id, and number of mach messages
|
// ->returns dictionary of process id, and number of mach messages
|
||||||
currentSenders = [self enumMachSenders:coreAudio];
|
currentSenders = [self enumMachSenders:self.coreAudioProcess];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -510,7 +567,8 @@ bail:
|
||||||
|
|
||||||
}//sync
|
}//sync
|
||||||
|
|
||||||
//bail
|
}//pool
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return audioProcs;
|
return audioProcs;
|
||||||
|
@ -523,6 +581,10 @@ bail:
|
||||||
//senders
|
//senders
|
||||||
NSMutableDictionary* senders = nil;
|
NSMutableDictionary* senders = nil;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//results from 'lsmp' cmd
|
//results from 'lsmp' cmd
|
||||||
NSString* results = nil;
|
NSString* results = nil;
|
||||||
|
|
||||||
|
@ -611,7 +673,8 @@ bail:
|
||||||
senders[processID] = @([senders[processID] unsignedIntegerValue] + 1);
|
senders[processID] = @([senders[processID] unsignedIntegerValue] + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//bail
|
}//pool
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return senders;
|
return senders;
|
||||||
|
@ -621,6 +684,13 @@ bail:
|
||||||
// ->returns dictionary of process id, and number of user client entries
|
// ->returns dictionary of process id, and number of user client entries
|
||||||
-(NSMutableDictionary*)enumDomainUserClients
|
-(NSMutableDictionary*)enumDomainUserClients
|
||||||
{
|
{
|
||||||
|
//array of RootDomainUserClients
|
||||||
|
NSMutableDictionary* clients = nil;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//matching service
|
//matching service
|
||||||
io_service_t matchingService = 0;
|
io_service_t matchingService = 0;
|
||||||
|
|
||||||
|
@ -630,9 +700,6 @@ bail:
|
||||||
//kids
|
//kids
|
||||||
io_registry_entry_t child = 0;
|
io_registry_entry_t child = 0;
|
||||||
|
|
||||||
//array of RootDomainUserClients
|
|
||||||
NSMutableDictionary* clients = nil;
|
|
||||||
|
|
||||||
//client creator
|
//client creator
|
||||||
CFTypeRef creator = 0;
|
CFTypeRef creator = 0;
|
||||||
|
|
||||||
|
@ -670,6 +737,9 @@ bail:
|
||||||
//always release child
|
//always release child
|
||||||
IOObjectRelease(child);
|
IOObjectRelease(child);
|
||||||
|
|
||||||
|
//unset
|
||||||
|
child = 0;
|
||||||
|
|
||||||
//if couldn't get a creator
|
//if couldn't get a creator
|
||||||
// ->might just not be of RootDomainUserClient, so skip
|
// ->might just not be of RootDomainUserClient, so skip
|
||||||
if(0 == creator)
|
if(0 == creator)
|
||||||
|
@ -696,9 +766,11 @@ bail:
|
||||||
|
|
||||||
//release
|
//release
|
||||||
CFRelease(creator);
|
CFRelease(creator);
|
||||||
|
|
||||||
|
//unset
|
||||||
|
creator = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
//release iterator
|
//release iterator
|
||||||
|
@ -706,6 +778,9 @@ bail:
|
||||||
{
|
{
|
||||||
//release
|
//release
|
||||||
IOObjectRelease(iterator);
|
IOObjectRelease(iterator);
|
||||||
|
|
||||||
|
//unset
|
||||||
|
iterator = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//release obj
|
//release obj
|
||||||
|
@ -713,10 +788,14 @@ bail:
|
||||||
{
|
{
|
||||||
//release
|
//release
|
||||||
IOObjectRelease(matchingService);
|
IOObjectRelease(matchingService);
|
||||||
|
|
||||||
|
//unset
|
||||||
|
matchingService = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return clients;
|
}//pool
|
||||||
|
|
||||||
|
return clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
//invoke 'sample' to confirm candidates are using CMIO/video/av inputs
|
//invoke 'sample' to confirm candidates are using CMIO/video/av inputs
|
||||||
|
@ -726,6 +805,10 @@ bail:
|
||||||
//av procs
|
//av procs
|
||||||
NSMutableArray* avProcs = nil;
|
NSMutableArray* avProcs = nil;
|
||||||
|
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//results from 'sample' cmd
|
//results from 'sample' cmd
|
||||||
NSString* results = nil;
|
NSString* results = nil;
|
||||||
|
|
||||||
|
@ -807,6 +890,8 @@ bail:
|
||||||
[avProcs addObject:processID];
|
[avProcs addObject:processID];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
return avProcs;
|
return avProcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,6 +899,10 @@ bail:
|
||||||
// ->this looks for that file and deletes it
|
// ->this looks for that file and deletes it
|
||||||
-(void)deleteSampleFile:(NSString*)processPath
|
-(void)deleteSampleFile:(NSString*)processPath
|
||||||
{
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//error
|
//error
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
|
|
||||||
|
@ -865,6 +954,8 @@ bail:
|
||||||
|
|
||||||
}//all files
|
}//all files
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
@ -876,8 +967,9 @@ bail:
|
||||||
// ->extra logic is executed to 'refresh' iVars when video is disabled
|
// ->extra logic is executed to 'refresh' iVars when video is disabled
|
||||||
-(void)updateVideoStatus:(BOOL)isEnabled
|
-(void)updateVideoStatus:(BOOL)isEnabled
|
||||||
{
|
{
|
||||||
//camera assistant
|
//pool
|
||||||
pid_t cameraAssistant = 0;
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//sync
|
//sync
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
|
@ -889,16 +981,23 @@ bail:
|
||||||
// ->re-enumerate mach senders
|
// ->re-enumerate mach senders
|
||||||
if(YES != isEnabled)
|
if(YES != isEnabled)
|
||||||
{
|
{
|
||||||
//first, look for 'VDCAssistant'
|
//find camera assistant
|
||||||
cameraAssistant = findProcess(VDC_ASSISTANT);
|
// only do this once, or again, if it died
|
||||||
if(0 == cameraAssistant)
|
if( (0 == self.cameraAssistantProcess) ||
|
||||||
|
(YES != isProcessAlive(self.cameraAssistantProcess)) )
|
||||||
{
|
{
|
||||||
//look for 'AppleCameraAssistant'
|
//find camera assistant
|
||||||
cameraAssistant = findProcess(APPLE_CAMERA_ASSISTANT);
|
// ->first look for 'VDCAssistant'
|
||||||
|
self.cameraAssistantProcess = findProcess(VDC_ASSISTANT);
|
||||||
|
if(0 == self.cameraAssistantProcess)
|
||||||
|
{
|
||||||
|
//look for 'AppleCameraAssistant'
|
||||||
|
self.cameraAssistantProcess = findProcess(APPLE_CAMERA_ASSISTANT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//sanity check
|
//sanity check
|
||||||
if(0 == cameraAssistant)
|
if(0 == self.cameraAssistantProcess)
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, @"failed to find VDCAssistant/AppleCameraAssistant process");
|
logMsg(LOG_ERR, @"failed to find VDCAssistant/AppleCameraAssistant process");
|
||||||
|
@ -908,11 +1007,13 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//enumerate mach senders
|
//enumerate mach senders
|
||||||
self.machSendersVideo = [self enumMachSenders:cameraAssistant];
|
self.machSendersVideo = [self enumMachSenders:self.cameraAssistantProcess];
|
||||||
}
|
}
|
||||||
|
|
||||||
}//sync
|
}//sync
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
@ -923,6 +1024,10 @@ bail:
|
||||||
// ->extra logic is executed to 'refresh' iVars when audio is disabled
|
// ->extra logic is executed to 'refresh' iVars when audio is disabled
|
||||||
-(void)updateAudioStatus:(BOOL)isEnabled
|
-(void)updateAudioStatus:(BOOL)isEnabled
|
||||||
{
|
{
|
||||||
|
//pool
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
|
||||||
//sync
|
//sync
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
|
@ -933,14 +1038,30 @@ bail:
|
||||||
// ->re-enumerate mach senders & i/o registry user clients
|
// ->re-enumerate mach senders & i/o registry user clients
|
||||||
if(YES != isEnabled)
|
if(YES != isEnabled)
|
||||||
{
|
{
|
||||||
//enumerate mach senders
|
//find coreaudio
|
||||||
self.machSendersAudio = [self enumMachSenders:findProcess(CORE_AUDIO)];
|
//find core audio
|
||||||
|
// only do this once, or again, if it died
|
||||||
|
if( (0 == self.coreAudioProcess) ||
|
||||||
|
(YES != isProcessAlive(self.coreAudioProcess)) )
|
||||||
|
{
|
||||||
|
//find core audio
|
||||||
|
self.coreAudioProcess = findProcess(CORE_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
//enumerate i/o registry user clients
|
//enumerate
|
||||||
self.userClients = [self enumDomainUserClients];
|
if(0 != self.coreAudioProcess)
|
||||||
|
{
|
||||||
|
//enumerate mach senders
|
||||||
|
self.machSendersAudio = [self enumMachSenders:self.coreAudioProcess];
|
||||||
|
|
||||||
|
//enumerate i/o registry user clients
|
||||||
|
self.userClients = [self enumDomainUserClients];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}//pool
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.0</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright (c) 2017 Objective-See. All rights reserved.</string>
|
<string>Copyright (c) 2017 Objective-See. All rights reserved.</string>
|
||||||
<key>XPCService</key>
|
<key>XPCService</key>
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#import "Enumerator.h"
|
#import "Enumerator.h"
|
||||||
#import "OverSightXPC.h"
|
#import "OverSightXPC.h"
|
||||||
|
|
||||||
|
|
||||||
@implementation OverSightXPC
|
@implementation OverSightXPC
|
||||||
|
|
||||||
@synthesize machSenders;
|
@synthesize machSenders;
|
||||||
|
@ -23,7 +22,7 @@
|
||||||
-(void)initialize:(void (^)(void))reply
|
-(void)initialize:(void (^)(void))reply
|
||||||
{
|
{
|
||||||
//start enumerating
|
//start enumerating
|
||||||
// ->will forever baseline current mach msg procs
|
// will forever baseline current mach msg procs
|
||||||
[NSThread detachNewThreadSelector:@selector(start) toTarget:[Enumerator sharedManager] withObject:nil];
|
[NSThread detachNewThreadSelector:@selector(start) toTarget:[Enumerator sharedManager] withObject:nil];
|
||||||
|
|
||||||
//reply
|
//reply
|
||||||
|
@ -32,6 +31,23 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//heartbeat
|
||||||
|
// need as otherwise kernel might kill XPC
|
||||||
|
-(void)heartBeat:(void (^)(BOOL))reply
|
||||||
|
{
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"heartbeat request");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//nap
|
||||||
|
[NSThread sleepForTimeInterval:3.0f];
|
||||||
|
|
||||||
|
reply(YES);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//call into emumerate to get (new) video proc
|
//call into emumerate to get (new) video proc
|
||||||
-(void)getVideoProcs:(BOOL)polling reply:(void (^)(NSMutableArray *))reply
|
-(void)getVideoProcs:(BOOL)polling reply:(void (^)(NSMutableArray *))reply
|
||||||
{
|
{
|
||||||
|
@ -118,7 +134,6 @@
|
||||||
//happy
|
//happy
|
||||||
wasAdded = YES;
|
wasAdded = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
//reply
|
//reply
|
||||||
|
@ -192,7 +207,6 @@ bail:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
//reply
|
//reply
|
||||||
|
@ -220,7 +234,6 @@ bail:
|
||||||
//happy
|
//happy
|
||||||
wasKilled = YES;
|
wasKilled = YES;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
//reply
|
//reply
|
||||||
|
@ -236,7 +249,4 @@ bail:
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,4 @@ OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement)
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* main_h */
|
#endif /* main_h */
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "main.h"
|
#import "main.h"
|
||||||
|
#import "Logging.h"
|
||||||
|
|
||||||
/* GLOBALS */
|
/* GLOBALS */
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ pid_t clientPID = 0;
|
||||||
@implementation ServiceDelegate
|
@implementation ServiceDelegate
|
||||||
|
|
||||||
//automatically invoked
|
//automatically invoked
|
||||||
//->allows NSXPCListener to configure/accept/resume a new incoming NSXPCConnection
|
// allows NSXPCListener to configure/accept/resume a new incoming NSXPCConnection
|
||||||
// note: we only allow binaries signed by Objective-See to talk to this!
|
// note: we only allow binaries signed by Objective-See to connect & talk to this!
|
||||||
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
|
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
|
||||||
{
|
{
|
||||||
//flag
|
//flag
|
||||||
|
@ -39,6 +39,11 @@ pid_t clientPID = 0;
|
||||||
//signing req string
|
//signing req string
|
||||||
NSString *requirementString = nil;
|
NSString *requirementString = nil;
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"new client connection");
|
||||||
|
#endif
|
||||||
|
|
||||||
//init signing req string
|
//init signing req string
|
||||||
requirementString = [NSString stringWithFormat:@"anchor trusted and certificate leaf [subject.CN] = \"%@\"", SIGNING_AUTH];
|
requirementString = [NSString stringWithFormat:@"anchor trusted and certificate leaf [subject.CN] = \"%@\"", SIGNING_AUTH];
|
||||||
|
|
||||||
|
@ -68,11 +73,16 @@ pid_t clientPID = 0;
|
||||||
//resume
|
//resume
|
||||||
[newConnection resume];
|
[newConnection resume];
|
||||||
|
|
||||||
|
//grab client/requestor's pid
|
||||||
|
clientPID = audit_token_to_pid(((ExtendedNSXPCConnection*)newConnection).auditToken);
|
||||||
|
|
||||||
//happy
|
//happy
|
||||||
shouldAccept = YES;
|
shouldAccept = YES;
|
||||||
|
|
||||||
//grab client/requestor's pid
|
//dbg msg
|
||||||
clientPID = audit_token_to_pid(((ExtendedNSXPCConnection*)newConnection).auditToken);
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"accepted new client connection (pid: %d)", clientPID]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
@ -110,7 +120,7 @@ int main(int argc, const char *argv[])
|
||||||
installExceptionHandlers();
|
installExceptionHandlers();
|
||||||
|
|
||||||
//create the delegate for the service.
|
//create the delegate for the service.
|
||||||
delegate = [ServiceDelegate new];
|
delegate = [[ServiceDelegate alloc] init];
|
||||||
|
|
||||||
//set up the one NSXPCListener for this service
|
//set up the one NSXPCListener for this service
|
||||||
// ->handles incoming connections
|
// ->handles incoming connections
|
||||||
|
@ -126,7 +136,6 @@ int main(int argc, const char *argv[])
|
||||||
//happy
|
//happy
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12121" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12121"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||||
<rect key="contentRect" x="196" y="240" width="486" height="301"/>
|
<rect key="contentRect" x="196" y="240" width="486" height="301"/>
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1058"/>
|
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
|
||||||
<view key="contentView" id="se5-gp-TjO">
|
<view key="contentView" id="se5-gp-TjO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="486" height="301"/>
|
<rect key="frame" x="0.0" y="0.0" width="486" height="301"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
||||||
<rect key="frame" x="158" y="220" width="182" height="19"/>
|
<rect key="frame" x="158" y="220" width="182" height="19"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Version:" id="bBK-v0-ypq">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Version:" id="bBK-v0-ypq">
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#define PRODUCT_URL @"https://objective-see.com/products/oversight.html"
|
#define PRODUCT_URL @"https://objective-see.com/products/oversight.html"
|
||||||
|
|
||||||
//product version url
|
//product version url
|
||||||
#define PRODUCT_VERSION_URL @"https://objective-see.com/products.json"
|
#define PRODUCT_VERSIONS_URL @"https://objective-see.com/products.json"
|
||||||
|
|
||||||
//patreon url
|
//patreon url
|
||||||
#define PATREON_URL @"https://www.patreon.com/objective_see"
|
#define PATREON_URL @"https://www.patreon.com/objective_see"
|
||||||
|
@ -129,9 +129,6 @@
|
||||||
//path to xattr
|
//path to xattr
|
||||||
#define XATTR @"/usr/bin/xattr"
|
#define XATTR @"/usr/bin/xattr"
|
||||||
|
|
||||||
//path to sudo
|
|
||||||
#define SUDO @"/usr/bin/sudo"
|
|
||||||
|
|
||||||
//path to facetime
|
//path to facetime
|
||||||
#define FACE_TIME @"/Applications/FaceTime.app/Contents/MacOS/FaceTime"
|
#define FACE_TIME @"/Applications/FaceTime.app/Contents/MacOS/FaceTime"
|
||||||
|
|
||||||
|
@ -187,5 +184,4 @@
|
||||||
//log to file flag
|
//log to file flag
|
||||||
#define LOG_TO_FILE 0x10
|
#define LOG_TO_FILE 0x10
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#import <signal.h>
|
#import <signal.h>
|
||||||
|
|
||||||
//install exception/signal handlers
|
//install exception/signal handlers
|
||||||
void installExceptionHandlers();
|
void installExceptionHandlers(void);
|
||||||
|
|
||||||
//exception handler for Obj-C exceptions
|
//exception handler for Obj-C exceptions
|
||||||
void exceptionHandler(NSException *exception);
|
void exceptionHandler(NSException *exception);
|
||||||
|
@ -19,6 +19,3 @@ void signalHandler(int signal, siginfo_t *info, void *context);
|
||||||
|
|
||||||
//display error window
|
//display error window
|
||||||
void displayErrorWindow(NSDictionary* errorInfo);
|
void displayErrorWindow(NSDictionary* errorInfo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,13 @@
|
||||||
void logMsg(int level, NSString* msg);
|
void logMsg(int level, NSString* msg);
|
||||||
|
|
||||||
//prep/open log file
|
//prep/open log file
|
||||||
BOOL initLogging();
|
BOOL initLogging(void);
|
||||||
|
|
||||||
//get path to log file
|
//get path to log file
|
||||||
NSString* logFilePath();
|
NSString* logFilePath(void);
|
||||||
|
|
||||||
//de-init logging
|
//de-init logging
|
||||||
void deinitLogging();
|
void deinitLogging(void);
|
||||||
|
|
||||||
//log to file
|
//log to file
|
||||||
void log2File(NSString* msg);
|
void log2File(NSString* msg);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ void logMsg(int level, NSString* msg)
|
||||||
level &= ~LOG_TO_FILE;
|
level &= ~LOG_TO_FILE;
|
||||||
|
|
||||||
//alloc/init
|
//alloc/init
|
||||||
// ->always start w/ 'OVERSIGHT' + pid
|
// ->always start w/ 'LULU' + pid
|
||||||
logPrefix = [NSMutableString stringWithFormat:@"OVERSIGHT(%d)", getpid()];
|
logPrefix = [NSMutableString stringWithFormat:@"OVERSIGHT(%d)", getpid()];
|
||||||
|
|
||||||
//if its error, add error to prefix
|
//if its error, add error to prefix
|
||||||
|
@ -44,8 +44,8 @@ void logMsg(int level, NSString* msg)
|
||||||
//debug mode logic
|
//debug mode logic
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
//in debug mode. promote debug msgs to LOG_NOTICE
|
//in debug mode promote debug msgs to LOG_NOTICE
|
||||||
// ->OS X/macOS only shows LOG_NOTICE and above in the system log
|
// OSX/macOS only shows LOG_NOTICE and above
|
||||||
if(LOG_DEBUG == level)
|
if(LOG_DEBUG == level)
|
||||||
{
|
{
|
||||||
//promote
|
//promote
|
||||||
|
@ -54,29 +54,23 @@ void logMsg(int level, NSString* msg)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//log to syslog
|
//log to syslog if a level was specified
|
||||||
syslog(level, "%s: %s", [logPrefix UTF8String], [msg UTF8String]);
|
// as code doesn't use LOG_EMERG (0), this check is ok
|
||||||
|
if(0 != level)
|
||||||
|
{
|
||||||
|
//log to syslog
|
||||||
|
syslog(level, "%s: %s", [logPrefix UTF8String], [msg UTF8String]);
|
||||||
|
}
|
||||||
|
|
||||||
//when a message is to be logged to file
|
//when a message is to be logged to file
|
||||||
// ->log it to file and syslog, when logging is enabled
|
// ->log it, when logging is enabled
|
||||||
if(YES == shouldLog)
|
if(YES == shouldLog)
|
||||||
{
|
{
|
||||||
//but only when logging is enabled
|
//but only when logging is enable
|
||||||
if(nil != logFileHandle)
|
if(nil != logFileHandle)
|
||||||
{
|
{
|
||||||
//log
|
//log
|
||||||
log2File(msg);
|
log2File(msg);
|
||||||
|
|
||||||
//promote to notice for syslog
|
|
||||||
if(LOG_DEBUG == level)
|
|
||||||
{
|
|
||||||
//promote
|
|
||||||
level = LOG_NOTICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//also syslog
|
|
||||||
// ->should result in 1 log msg, (in release), as all LOG_TO_FILE are at LOG_DEBUG level
|
|
||||||
syslog(level, "%s: %s", [logPrefix UTF8String], [msg UTF8String]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
/* FUNCTIONS */
|
/* FUNCTIONS */
|
||||||
|
|
||||||
//get OS version
|
//get OS version
|
||||||
NSDictionary* getOSVersion();
|
NSDictionary* getOSVersion(void);
|
||||||
|
|
||||||
//get app's version
|
//get app's version
|
||||||
// ->extracted from Info.plist
|
// ->extracted from Info.plist
|
||||||
NSString* getAppVersion();
|
NSString* getAppVersion(void);
|
||||||
|
|
||||||
//set dir's|file's group/owner
|
//set dir's|file's group/owner
|
||||||
BOOL setFileOwner(NSString* path, NSNumber* groupID, NSNumber* ownerID, BOOL recursive);
|
BOOL setFileOwner(NSString* path, NSNumber* groupID, NSNumber* ownerID, BOOL recursive);
|
||||||
|
@ -39,10 +39,10 @@ NSBundle* findAppBundle(NSString* binaryPath);
|
||||||
|
|
||||||
//get app's version
|
//get app's version
|
||||||
// ->extracted from Info.plist
|
// ->extracted from Info.plist
|
||||||
NSString* getAppVersion();
|
NSString* getAppVersion(void);
|
||||||
|
|
||||||
//query interwebz to get latest version
|
//query interwebz to get latest version
|
||||||
NSString* getLatestVersion();
|
NSString* getLatestVersion(void);
|
||||||
|
|
||||||
//determine if there is a new version
|
//determine if there is a new version
|
||||||
// -1, YES or NO
|
// -1, YES or NO
|
||||||
|
@ -72,7 +72,8 @@ void makeModal(NSWindowController* windowController);
|
||||||
BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag);
|
BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag);
|
||||||
|
|
||||||
//get logged in user
|
//get logged in user
|
||||||
NSString* loggedinUser();
|
// name, uid, and gid
|
||||||
|
NSMutableDictionary* loggedinUser(void);
|
||||||
|
|
||||||
//find a process by name
|
//find a process by name
|
||||||
pid_t findProcess(NSString* processName);
|
pid_t findProcess(NSString* processName);
|
||||||
|
@ -81,6 +82,9 @@ pid_t findProcess(NSString* processName);
|
||||||
void makeTextViewHyperlink(NSTextField* textField, NSURL* url);
|
void makeTextViewHyperlink(NSTextField* textField, NSURL* url);
|
||||||
|
|
||||||
//get active application
|
//get active application
|
||||||
pid_t frontmostApplication();
|
pid_t frontmostApplication(void);
|
||||||
|
|
||||||
|
//check if process is alive
|
||||||
|
BOOL isProcessAlive(pid_t processID);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -274,17 +274,27 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments, BOOL shouldWait)
|
||||||
//output
|
//output
|
||||||
NSData *output = nil;
|
NSData *output = nil;
|
||||||
|
|
||||||
|
//dispatch group
|
||||||
|
dispatch_group_t dispatchGroup = 0;
|
||||||
|
|
||||||
//init task
|
//init task
|
||||||
task = [NSTask new];
|
task = [[NSTask alloc] init];
|
||||||
|
|
||||||
//init pipe
|
//init pipe
|
||||||
outPipe = [NSPipe pipe];
|
outPipe = [NSPipe pipe];
|
||||||
|
|
||||||
|
//create dispatch group
|
||||||
|
dispatchGroup = dispatch_group_create();
|
||||||
|
|
||||||
//set task's path
|
//set task's path
|
||||||
task.launchPath = binaryPath;
|
task.launchPath = binaryPath;
|
||||||
|
|
||||||
//set task's args
|
//set task's args
|
||||||
task.arguments = arguments;
|
if(nil != arguments)
|
||||||
|
{
|
||||||
|
//add
|
||||||
|
task.arguments = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
//set task's output to pipe
|
//set task's output to pipe
|
||||||
// ->but only if we're waiting for exit
|
// ->but only if we're waiting for exit
|
||||||
|
@ -299,6 +309,16 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments, BOOL shouldWait)
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"@exec'ing %@ (args: %@)", binaryPath, arguments]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"@exec'ing %@ (args: %@)", binaryPath, arguments]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//enter dispatch
|
||||||
|
dispatch_group_enter(dispatchGroup);
|
||||||
|
|
||||||
|
//set task's termination to leave dispatch group
|
||||||
|
task.terminationHandler = ^(NSTask *task){
|
||||||
|
|
||||||
|
//leave
|
||||||
|
dispatch_group_leave(dispatchGroup);
|
||||||
|
};
|
||||||
|
|
||||||
//wrap task launch
|
//wrap task launch
|
||||||
@try
|
@try
|
||||||
{
|
{
|
||||||
|
@ -333,7 +353,7 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments, BOOL shouldWait)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//wait till exit
|
//wait till exit
|
||||||
[task waitUntilExit];
|
dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -345,6 +365,7 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments, BOOL shouldWait)
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,59 +777,54 @@ bail:
|
||||||
//query interwebz to get latest version
|
//query interwebz to get latest version
|
||||||
NSString* getLatestVersion()
|
NSString* getLatestVersion()
|
||||||
{
|
{
|
||||||
//version data
|
//product version(s) data
|
||||||
__block NSData* versionData = nil;
|
NSData* productsVersionData = nil;
|
||||||
|
|
||||||
//version dictionary
|
//version dictionary
|
||||||
NSDictionary* versionDictionary = nil;
|
NSDictionary* productsVersionDictionary = nil;
|
||||||
|
|
||||||
//latest version
|
//latest version
|
||||||
NSString* latestVersion = nil;
|
NSString* latestVersion = nil;
|
||||||
|
|
||||||
//run in background if main thread
|
//get version from remote URL
|
||||||
if(YES == [NSThread isMainThread])
|
productsVersionData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:PRODUCT_VERSIONS_URL]];
|
||||||
{
|
if(nil == productsVersionData)
|
||||||
//run in background
|
|
||||||
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
|
||||||
^{
|
|
||||||
//get version data
|
|
||||||
versionData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:PRODUCT_VERSION_URL]];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//no need to background
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//get version from remote URL
|
|
||||||
versionData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:PRODUCT_VERSION_URL]];
|
|
||||||
}
|
|
||||||
|
|
||||||
//sanity check
|
|
||||||
if(nil == versionData)
|
|
||||||
{
|
{
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
//convert JSON to dictionary
|
//convert JSON to dictionary
|
||||||
versionDictionary = [NSJSONSerialization JSONObjectWithData:versionData options:0 error:nil];
|
// ->wrap as may throw exception
|
||||||
|
@try
|
||||||
//sanity check
|
{
|
||||||
if(nil == versionDictionary)
|
//convert
|
||||||
|
productsVersionDictionary = [NSJSONSerialization JSONObjectWithData:productsVersionData options:0 error:nil];
|
||||||
|
if(nil == productsVersionDictionary)
|
||||||
|
{
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@catch(NSException* exception)
|
||||||
{
|
{
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract latest version
|
//extract latest version
|
||||||
latestVersion = versionDictionary[@"latestVersion"];
|
latestVersion = [[productsVersionDictionary objectForKey:@"OverSight"] objectForKey:@"version"];
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"latest version: %@", latestVersion]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
return latestVersion;
|
return latestVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//wait until a window is non nil
|
//wait until a window is non nil
|
||||||
// ->then make it modal
|
// ->then make it modal
|
||||||
void makeModal(NSWindowController* windowController)
|
void makeModal(NSWindowController* windowController)
|
||||||
|
@ -981,14 +997,27 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//get logged in user
|
//get logged in user
|
||||||
NSString* loggedinUser()
|
// name, uid, and gid
|
||||||
|
NSMutableDictionary* loggedinUser()
|
||||||
{
|
{
|
||||||
|
//user info
|
||||||
|
NSMutableDictionary* userInfo = nil;
|
||||||
|
|
||||||
//store
|
//store
|
||||||
SCDynamicStoreRef store = nil;
|
SCDynamicStoreRef store = nil;
|
||||||
|
|
||||||
//user
|
//user
|
||||||
NSString* user = nil;
|
NSString* user = nil;
|
||||||
|
|
||||||
|
//uid
|
||||||
|
uid_t uid = 0;
|
||||||
|
|
||||||
|
//gid
|
||||||
|
gid_t gid = 0;
|
||||||
|
|
||||||
|
//allco dictionary
|
||||||
|
userInfo = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
//create store
|
//create store
|
||||||
store = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
|
store = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
|
||||||
if(NULL == store)
|
if(NULL == store)
|
||||||
|
@ -997,8 +1026,17 @@ NSString* loggedinUser()
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get user
|
//get user and uid/gid
|
||||||
user = CFBridgingRelease(SCDynamicStoreCopyConsoleUser(store, NULL, NULL));
|
user = CFBridgingRelease(SCDynamicStoreCopyConsoleUser(store, &uid, &gid));
|
||||||
|
|
||||||
|
//add user
|
||||||
|
userInfo[@"user"] = user;
|
||||||
|
|
||||||
|
//add uid
|
||||||
|
userInfo[@"uid"] = [NSNumber numberWithUnsignedInt:uid];
|
||||||
|
|
||||||
|
//add uid
|
||||||
|
userInfo[@"gid"] = [NSNumber numberWithUnsignedInt:gid];
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
@ -1010,7 +1048,7 @@ bail:
|
||||||
CFRelease(store);
|
CFRelease(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
//find a process by name
|
//find a process by name
|
||||||
|
@ -1059,7 +1097,7 @@ pid_t findProcess(NSString* processName)
|
||||||
//get name
|
//get name
|
||||||
processPath = getProcessPath(pids[i]);
|
processPath = getProcessPath(pids[i]);
|
||||||
if( (nil == processPath) ||
|
if( (nil == processPath) ||
|
||||||
(0 == processPath.length) )
|
(0 == processPath.length) )
|
||||||
{
|
{
|
||||||
//skip
|
//skip
|
||||||
continue;
|
continue;
|
||||||
|
@ -1134,3 +1172,31 @@ pid_t frontmostApplication()
|
||||||
return NSWorkspace.sharedWorkspace.frontmostApplication.processIdentifier;
|
return NSWorkspace.sharedWorkspace.frontmostApplication.processIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check if process is alive
|
||||||
|
BOOL isProcessAlive(pid_t processID)
|
||||||
|
{
|
||||||
|
//ret var
|
||||||
|
BOOL bIsAlive = NO;
|
||||||
|
|
||||||
|
//signal status
|
||||||
|
int signalStatus = -1;
|
||||||
|
|
||||||
|
//send kill with 0 to determine if alive
|
||||||
|
// -> see: http://stackoverflow.com/questions/9152979/check-if-process-exists-given-its-pid
|
||||||
|
signalStatus = kill(processID, 0);
|
||||||
|
|
||||||
|
//is alive?
|
||||||
|
if( (0 == signalStatus) ||
|
||||||
|
( (0 != signalStatus) && (errno != ESRCH) ) )
|
||||||
|
{
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"agent (%d) is ALIVE", processID]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//alive!
|
||||||
|
bIsAlive = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bIsAlive;
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
//start enumerator
|
//start enumerator
|
||||||
-(void)initialize:(void (^)(void))reply;
|
-(void)initialize:(void (^)(void))reply;
|
||||||
|
|
||||||
|
//heartbeat
|
||||||
|
// need as otherwise kernel might kill XPC
|
||||||
|
-(void)heartBeat:(void (^)(BOOL))reply;
|
||||||
|
|
||||||
//get (new) audio procs
|
//get (new) audio procs
|
||||||
-(void)getAudioProcs:(void (^)(NSMutableArray *))reply;
|
-(void)getAudioProcs:(void (^)(NSMutableArray *))reply;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
patrick wardle
|
Loading…
Reference in New Issue