This commit is contained in:
opa334
2022-09-09 20:22:34 +02:00
parent ab3261f0f2
commit 5d474901a2
16 changed files with 533 additions and 235 deletions
+1 -1
View File
@@ -50,7 +50,7 @@
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1.0.7</string>
<string>1.0.8</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIDeviceFamily</key>
+84 -12
View File
@@ -28,6 +28,48 @@
self.tableView.allowsMultipleSelectionDuringEditing = NO;
}
- (void)showError:(NSError*)error
{
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Error %ld", error.code] message:error.localizedDescription preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
[errorAlert addAction:closeAction];
[self presentViewController:errorAlert animated:YES completion:nil];
}
- (void)uninstallPressedForRowAtIndexPath:(NSIndexPath*)indexPath
{
TSApplicationsManager* appsManager = [TSApplicationsManager sharedInstance];
NSString* appPath = [appsManager installedAppPaths][indexPath.row];
NSString* appId = [appsManager appIdForAppPath:appPath];
NSString* appName = [appsManager displayNameForAppPath:appPath];
UIAlertController* confirmAlert = [UIAlertController alertControllerWithTitle:@"Confirm Uninstallation" message:[NSString stringWithFormat:@"Uninstalling the app '%@' will delete the app and all data associated to it.", appName] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* uninstallAction = [UIAlertAction actionWithTitle:@"Uninstall" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
{
if(appId)
{
[appsManager uninstallApp:appId];
}
else
{
[appsManager uninstallAppByPath:appPath];
}
}];
[confirmAlert addAction:uninstallAction];
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
[confirmAlert addAction:cancelAction];
[self presentViewController:confirmAlert animated:YES completion:nil];
}
- (void)deselectRow
{
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@@ -51,20 +93,50 @@
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
if(editingStyle == UITableViewCellEditingStyleDelete)
{
NSString* appPath = [[TSApplicationsManager sharedInstance] installedAppPaths][indexPath.row];
NSString* appId = [[TSApplicationsManager sharedInstance] appIdForAppPath:appPath];
if(appId)
{
[[TSApplicationsManager sharedInstance] uninstallApp:appId];
}
else
{
[[TSApplicationsManager sharedInstance] uninstallAppByPath:appPath];
}
[self uninstallPressedForRowAtIndexPath:indexPath];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
TSApplicationsManager* appsManager = [TSApplicationsManager sharedInstance];
NSString* appPath = [appsManager installedAppPaths][indexPath.row];
NSString* appId = [appsManager appIdForAppPath:appPath];
NSString* appName = [appsManager displayNameForAppPath:appPath];
UIAlertController* appSelectAlert = [UIAlertController alertControllerWithTitle:appName message:appId preferredStyle:UIAlertControllerStyleActionSheet];
/*UIAlertAction* detachAction = [UIAlertAction actionWithTitle:@"Detach from TrollStore" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
int detachRet = [appsManager detachFromApp:appId];
if(detachRet != 0)
{
[self showError:[appsManager errorForCode:detachRet]];
}
[self deselectRow];
}];
[appSelectAlert addAction:detachAction];*/
UIAlertAction* uninstallAction = [UIAlertAction actionWithTitle:@"Uninstall App" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
{
[self uninstallPressedForRowAtIndexPath:indexPath];
[self deselectRow];
}];
[appSelectAlert addAction:uninstallAction];
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction* action)
{
[self deselectRow];
}];
[appSelectAlert addAction:cancelAction];
appSelectAlert.popoverPresentationController.sourceView = tableView;
appSelectAlert.popoverPresentationController.sourceRect = [tableView rectForRowAtIndexPath:indexPath];
[self presentViewController:appSelectAlert animated:YES completion:nil];
}
@end
+2 -1
View File
@@ -14,9 +14,10 @@
- (NSString*)displayNameForAppPath:(NSString*)appPath;
- (NSError*)errorForCode:(int)code;
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force;
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force log:(NSString**)logOut;
- (int)installIpa:(NSString*)pathToIpa;
- (int)uninstallApp:(NSString*)appId;
- (int)uninstallAppByPath:(NSString*)path;
//- (int)detachFromApp:(NSString*)appId;
@end
+44 -10
View File
@@ -24,7 +24,13 @@
- (NSDictionary*)infoDictionaryForAppPath:(NSString*)appPath
{
NSString* infoPlistPath = [appPath stringByAppendingPathComponent:@"Info.plist"];
return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
NSError* error;
NSDictionary* infoDict = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:infoPlistPath] error:&error];
if(error)
{
NSLog(@"error getting info dict: %@", error);
}
return infoDict;
}
- (NSString*)appIdForAppPath:(NSString*)appPath
@@ -35,7 +41,6 @@
- (NSString*)displayNameForAppPath:(NSString*)appPath
{
NSDictionary* infoDict = [self infoDictionaryForAppPath:appPath];
NSString* displayName = infoDict[@"CFBundleDisplayName"];
if(![displayName isKindOfClass:[NSString class]]) displayName = nil;
if(!displayName || [displayName isEqualToString:@""])
@@ -57,12 +62,14 @@
NSString* errorDescription = @"Unknown Error";
switch(code)
{
// IPA install errors
case 166:
errorDescription = @"The IPA file does not exist or is not accessible.";
break;
case 167:
errorDescription = @"The IPA file does not appear to contain an app.";
break;
// App install errors
case 170:
errorDescription = @"Failed to create container for app bundle.";
break;
@@ -70,27 +77,46 @@
errorDescription = @"A non-TrollStore app with the same identifier is already installed. If you are absolutely sure it is not, you can force install it.";
break;
case 172:
errorDescription = @"The app does not seem to contain an Info.plist";
errorDescription = @"The app does not contain an Info.plist file.";
break;
case 173:
errorDescription = @"The app is not signed with a fake CoreTrust certificate and ldid does not seem to be installed. Make sure ldid is installed in the settings tab and try again.";
errorDescription = @"The app is not signed with a fake CoreTrust certificate and ldid is not installed. Install ldid in the settings tab and try again.";
break;
case 174:
errorDescription = @"The apps main executable does not exists.";
break;
case 175:
errorDescription = @"Failed to sign the app. ldid returned a non zero status code.";
break;
case 176:
errorDescription = @"The apps Info.plist is missing required values.";
break;
case 177:
errorDescription = @"Failed to mark app as TrollStore app.";
break;
case 178:
errorDescription = @"Failed to copy app bundle.";
break;
// App detach errors
/*case 184:
errorDescription = @"Refusing to detach, the app is still signed with a fake root certificate. The detach option is only for when you have installed an App Store app on top of a TrollStore app.";
break;*/
}
NSError* error = [NSError errorWithDomain:TrollStoreErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : errorDescription}];
return error;
}
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force log:(NSString**)logOut
{
int ret;
if(force)
{
ret = spawnRoot(helperPath(), @[@"install", pathToIpa, @"force"]);
ret = spawnRoot(helperPath(), @[@"install", pathToIpa, @"force"], nil, logOut);
}
else
{
ret = spawnRoot(helperPath(), @[@"install", pathToIpa]);
ret = spawnRoot(helperPath(), @[@"install", pathToIpa], nil, logOut);
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
return ret;
@@ -98,13 +124,13 @@
- (int)installIpa:(NSString*)pathToIpa
{
return [self installIpa:pathToIpa force:NO];
return [self installIpa:pathToIpa force:NO log:nil];
}
- (int)uninstallApp:(NSString*)appId
{
if(!appId) return -200;
int ret = spawnRoot(helperPath(), @[@"uninstall", appId]);
int ret = spawnRoot(helperPath(), @[@"uninstall", appId], nil, nil);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
return ret;
}
@@ -112,9 +138,17 @@
- (int)uninstallAppByPath:(NSString*)path
{
if(!path) return -200;
int ret = spawnRoot(helperPath(), @[@"uninstall-path", path]);
int ret = spawnRoot(helperPath(), @[@"uninstall-path", path], nil, nil);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
return ret;
}
/*- (int)detachFromApp:(NSString*)appId
{
if(!appId) return -200;
int ret = spawnRoot(helperPath(), @[@"detach", appId], nil, nil);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
return ret;
}*/
@end
+133 -116
View File
@@ -7,163 +7,180 @@
- (void)doIPAInstall:(NSString*)ipaPath scene:(UIWindowScene*)scene force:(BOOL)force completion:(void (^)(void))completion
{
UIWindow* keyWindow = nil;
for(UIWindow* window in scene.windows)
{
if(window.isKeyWindow)
{
keyWindow = window;
break;
}
}
UIWindow* keyWindow = nil;
for(UIWindow* window in scene.windows)
{
if(window.isKeyWindow)
{
keyWindow = window;
break;
}
}
UIAlertController* infoAlert = [UIAlertController alertControllerWithTitle:@"Installing" message:@"" preferredStyle:UIAlertControllerStyleAlert];
UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
[activityIndicator startAnimating];
[infoAlert.view addSubview:activityIndicator];
UIAlertController* infoAlert = [UIAlertController alertControllerWithTitle:@"Installing" message:@"" preferredStyle:UIAlertControllerStyleAlert];
UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
[activityIndicator startAnimating];
[infoAlert.view addSubview:activityIndicator];
[keyWindow.rootViewController presentViewController:infoAlert animated:YES completion:nil];
[keyWindow.rootViewController presentViewController:infoAlert animated:YES completion:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
// Install IPA
int ret = [[TSApplicationsManager sharedInstance] installIpa:ipaPath force:force];
NSError* error = [[TSApplicationsManager sharedInstance] errorForCode:ret];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
// Install IPA
//NSString* log;
int ret = [[TSApplicationsManager sharedInstance] installIpa:ipaPath force:force log:nil];
NSLog(@"installed app! ret:%d, error: %@", ret, error);
dispatch_async(dispatch_get_main_queue(), ^
{
[infoAlert dismissViewControllerAnimated:YES completion:^
{
if(ret != 0)
{
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Install Error %d", ret] message:[error localizedDescription] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
if(ret == 171)
{
completion();
}
}];
if(ret == 171)
{
UIAlertAction* forceInstallAction = [UIAlertAction actionWithTitle:@"Force Installation" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
[self doIPAInstall:ipaPath scene:scene force:YES completion:completion];
}];
[errorAlert addAction:forceInstallAction];
}
[errorAlert addAction:closeAction];
NSError* error;
if(ret != 0)
{
error = [[TSApplicationsManager sharedInstance] errorForCode:ret];
}
[keyWindow.rootViewController presentViewController:errorAlert animated:YES completion:nil];
}
NSLog(@"installed app! ret:%d, error: %@", ret, error);
if(ret != 171)
{
completion();
}
}];
});
});
dispatch_async(dispatch_get_main_queue(), ^
{
[infoAlert dismissViewControllerAnimated:YES completion:^
{
if(ret != 0)
{
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Install Error %d", ret] message:[error localizedDescription] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
if(ret == 171)
{
completion();
}
}];
[errorAlert addAction:closeAction];
if(ret == 171)
{
UIAlertAction* forceInstallAction = [UIAlertAction actionWithTitle:@"Force Installation" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
[self doIPAInstall:ipaPath scene:scene force:YES completion:completion];
}];
[errorAlert addAction:forceInstallAction];
}
else
{
/*UIAlertAction* copyLogAction = [UIAlertAction actionWithTitle:@"Copy Log" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = log;
}];
[errorAlert addAction:copyLogAction];*/
}
[keyWindow.rootViewController presentViewController:errorAlert animated:YES completion:nil];
}
if(ret != 171)
{
completion();
}
}];
});
});
}
- (void)handleURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts scene:(UIWindowScene*)scene
{
for(UIOpenURLContext* context in URLContexts)
{
NSLog(@"openURLContexts %@", context.URL);
NSURL* url = context.URL;
if (url != nil && [url isFileURL]) {
[url startAccessingSecurityScopedResource];
void (^doneBlock)(BOOL) = ^(BOOL shouldExit)
{
[url stopAccessingSecurityScopedResource];
[[NSFileManager defaultManager] removeItemAtURL:url error:nil];
for(UIOpenURLContext* context in URLContexts)
{
NSLog(@"openURLContexts %@", context.URL);
NSURL* url = context.URL;
if (url != nil && [url isFileURL]) {
[url startAccessingSecurityScopedResource];
void (^doneBlock)(BOOL) = ^(BOOL shouldExit)
{
[url stopAccessingSecurityScopedResource];
[[NSFileManager defaultManager] removeItemAtURL:url error:nil];
if(shouldExit)
{
NSLog(@"Respring + Exit");
respring();
exit(0);
}
};
if ([url.pathExtension isEqualToString:@"ipa"])
{
[self doIPAInstall:url.path scene:(UIWindowScene*)scene force:NO completion:^{
doneBlock(NO);
}];
}
else if([url.pathExtension isEqualToString:@"tar"])
{
// Update TrollStore itself
NSLog(@"Updating TrollStore...");
int ret = spawnRoot(helperPath(), @[@"install-trollstore", url.path]);
doneBlock(ret == 0);
NSLog(@"Updated TrollStore!");
}
}
}
if(shouldExit)
{
NSLog(@"Respring + Exit");
respring();
exit(0);
}
};
if ([url.pathExtension isEqualToString:@"ipa"])
{
[self doIPAInstall:url.path scene:(UIWindowScene*)scene force:NO completion:^{
doneBlock(NO);
}];
}
else if([url.pathExtension isEqualToString:@"tar"])
{
// Update TrollStore itself
NSLog(@"Updating TrollStore...");
int ret = spawnRoot(helperPath(), @[@"install-trollstore", url.path], nil, nil);
doneBlock(ret == 0);
NSLog(@"Updated TrollStore!");
}
}
}
}
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
NSLog(@"scene:%@ willConnectToSession:%@ options:%@", scene, session, connectionOptions);
UIWindowScene* windowScene = (UIWindowScene*)scene;
_window = [[UIWindow alloc] initWithWindowScene:windowScene];
_rootViewController = [[TSRootViewController alloc] init];
_window.rootViewController = _rootViewController;
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
NSLog(@"scene:%@ willConnectToSession:%@ options:%@", scene, session, connectionOptions);
UIWindowScene* windowScene = (UIWindowScene*)scene;
_window = [[UIWindow alloc] initWithWindowScene:windowScene];
_rootViewController = [[TSRootViewController alloc] init];
_window.rootViewController = _rootViewController;
[_window makeKeyAndVisible];
if(connectionOptions.URLContexts.count)
{
[self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene];
}
if(connectionOptions.URLContexts.count)
{
[self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene];
}
}
- (void)sceneDidDisconnect:(UIScene *)scene {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
- (void)sceneWillResignActive:(UIScene *)scene {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
- (void)sceneDidEnterBackground:(UIScene *)scene {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
{
NSLog(@"scene:%@ openURLContexts:%@", scene, URLContexts);
[self handleURLContexts:URLContexts scene:(UIWindowScene*)scene];
NSLog(@"scene:%@ openURLContexts:%@", scene, URLContexts);
[self handleURLContexts:URLContexts scene:(UIWindowScene*)scene];
}
@end
+5 -5
View File
@@ -225,7 +225,7 @@
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
spawnRoot(helperPath(), @[@"refresh-all"]);
spawnRoot(helperPath(), @[@"refresh-all"], nil, nil);
dispatch_async(dispatch_get_main_queue(), ^
{
@@ -259,7 +259,7 @@
}
else
{
spawnRoot(helperPath(), @[@"install-ldid", location.path]);
spawnRoot(helperPath(), @[@"install-ldid", location.path], nil, nil);
dispatch_async(dispatch_get_main_queue(), ^
{
[self stopActivityWithCompletion:nil];
@@ -294,7 +294,7 @@
{
UIAlertAction* installAction = [UIAlertAction actionWithTitle:[appProxy localizedName] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
{
spawnRoot(helperPath(), @[@"install-persistence-helper", appProxy.bundleIdentifier]);
spawnRoot(helperPath(), @[@"install-persistence-helper", appProxy.bundleIdentifier], nil, nil);
[self reloadSpecifiers];
}];
@@ -314,7 +314,7 @@
- (void)uninstallPersistenceHelperPressed
{
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"]);
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"], nil, nil);
[self reloadSpecifiers];
}
@@ -327,7 +327,7 @@
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
{
spawnRoot(helperPath(), @[@"uninstall-trollstore"]);
spawnRoot(helperPath(), @[@"uninstall-trollstore"], nil, nil);
exit(0);
}];
[uninstallWarningAlert addAction:continueAction];
+2 -1
View File
@@ -1,6 +1,7 @@
@import Foundation;
extern NSString* helperPath(void);
extern int spawnRoot(NSString* path, NSArray* args);
extern void printMultilineNSString(NSString* stringToPrint);
extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr);
extern void respring(void);
extern NSString* getTrollStoreVersion(void);
+58 -5
View File
@@ -14,7 +14,29 @@ NSString* helperPath(void)
return [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"trollstorehelper"];
}
int spawnRoot(NSString* path, NSArray* args)
NSString* getNSStringFromFile(int fd)
{
NSMutableString* ms = [NSMutableString new];
ssize_t num_read;
char c;
while((num_read = read(fd, &c, sizeof(c))))
{
[ms appendString:[NSString stringWithFormat:@"%c", c]];
}
return ms.copy;
}
void printMultilineNSString(NSString* stringToPrint)
{
NSCharacterSet *separator = [NSCharacterSet newlineCharacterSet];
NSArray* lines = [stringToPrint componentsSeparatedByCharactersInSet:separator];
for(NSString* line in lines)
{
NSLog(@"%@", line);
}
}
int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr)
{
NSMutableArray* argsM = args.mutableCopy ?: [NSMutableArray new];
[argsM insertObject:path.lastPathComponent atIndex:0];
@@ -28,18 +50,35 @@ int spawnRoot(NSString* path, NSArray* args)
}
argsC[argCount] = NULL;
int rv;
posix_spawnattr_t attr;
rv = posix_spawnattr_init(&attr);
if(rv != 0) return rv;
posix_spawnattr_init(&attr);
posix_spawnattr_set_persona_np(&attr, 99, POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE);
posix_spawnattr_set_persona_uid_np(&attr, 0);
posix_spawnattr_set_persona_gid_np(&attr, 0);
posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);
int outErr[2];
if(stdErr)
{
pipe(outErr);
posix_spawn_file_actions_adddup2(&action, outErr[1], STDERR_FILENO);
posix_spawn_file_actions_addclose(&action, outErr[0]);
}
int out[2];
if(stdOut)
{
pipe(out);
posix_spawn_file_actions_adddup2(&action, out[1], STDOUT_FILENO);
posix_spawn_file_actions_addclose(&action, out[0]);
}
pid_t task_pid;
int status = -200;
int spawnError = posix_spawn(&task_pid, [path UTF8String], NULL, &attr, (char* const*)argsC, NULL);
int spawnError = posix_spawn(&task_pid, [path UTF8String], &action, &attr, (char* const*)argsC, NULL);
posix_spawnattr_destroy(&attr);
for (NSUInteger i = 0; i < argCount; i++)
{
@@ -63,6 +102,20 @@ int spawnRoot(NSString* path, NSArray* args)
return -222;
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
if(stdOut)
{
close(out[1]);
NSString* output = getNSStringFromFile(out[0]);
*stdOut = output;
}
if(stdErr)
{
close(outErr[1]);
NSString* errorOutput = getNSStringFromFile(outErr[0]);
*stdErr = errorOutput;
}
return WEXITSTATUS(status);
}
+1 -1
View File
@@ -1,6 +1,6 @@
Package: com.opa334.trollstore
Name: TrollStore
Version: 1.0.7
Version: 1.0.8
Architecture: iphoneos-arm
Description: An awesome application!
Maintainer: opa334