diff --git a/Makefile b/Makefile
index d3dda1e..a7dece8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,11 @@
+ifeq ($(THEOS_PACKAGE_SCHEME),rootless)
+export TARGET = iphone:clang:14.4:15.0
+export ARCHS = arm64
+TweakSettings_XCODEFLAGS = GCC_PREPROCESSOR_DEFINITIONS='THEOS_PACKAGE_INSTALL_PREFIX=\"$(THEOS_PACKAGE_INSTALL_PREFIX)\"'
+else
export TARGET = iphone:clang:14.4:10.0
export ARCHS = armv7 arm64
+endif
DEBUG = 1
DEBUG_EXT =
@@ -14,7 +20,7 @@ include $(THEOS)/makefiles/common.mk
LAUNCH_URL =
XCODEPROJ_NAME = TweakSettings
-TweakSettings_XCODEFLAGS = PACKAGE_VERSION='@\"$(THEOS_PACKAGE_BASE_VERSION)\"'
+TweakSettings_XCODEFLAGS += PACKAGE_VERSION='@\"$(THEOS_PACKAGE_BASE_VERSION)\"'
TweakSettings_CODESIGN_FLAGS = -SResources/entitlements.plist
include $(THEOS_MAKE_PATH)/xcodeproj.mk
@@ -27,7 +33,8 @@ after-stage::
$(ECHO_NOTHING)rm -f $(THEOS_STAGING_DIR)/Applications/TweakSettings.app/Localizable.strings$(ECHO_END)
$(ECHO_NOTHING)/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${THEOS_PACKAGE_BASE_VERSION}" "${THEOS_STAGING_DIR}/Applications/${XCODEPROJ_NAME}.app/Info.plist"$(ECHO_END)
$(ECHO_NOTHING)/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${PACKAGE_VERSION}" "${THEOS_STAGING_DIR}/Applications/${XCODEPROJ_NAME}.app/Info.plist"$(ECHO_END)
- @echo "Set bundle version to: ${PACKAGE_VERSION}"
+ $(ECHO_BEGIN)$(PRINT_FORMAT_MAGENTA) "Set bundle version to: ${PACKAGE_VERSION}"$(ECHO_END)
+ $(ECHO_BEGIN)$(PRINT_FORMAT_MAGENTA) "Built for $(or $(THEOS_PACKAGE_SCHEME),rootful)"$(ECHO_END)
after-install::
- install.exec "killall -9 ${XCODEPROJ_NAME}; uicache -p /Applications/${XCODEPROJ_NAME}.app; uiopen tweaks:$(LAUNCH_URL)"
\ No newline at end of file
+ install.exec "killall -9 ${XCODEPROJ_NAME}; uicache -p $(THEOS_PACKAGE_INSTALL_PREFIX)/Applications/${XCODEPROJ_NAME}.app; uiopen tweaks:$(LAUNCH_URL)"
\ No newline at end of file
diff --git a/Releases/com.creaturecoding.tweaksettings_1.0.7_iphoneos-arm.deb b/Releases/com.creaturecoding.tweaksettings_1.0.7_iphoneos-arm.deb
new file mode 100644
index 0000000..02bfb0c
Binary files /dev/null and b/Releases/com.creaturecoding.tweaksettings_1.0.7_iphoneos-arm.deb differ
diff --git a/Releases/com.creaturecoding.tweaksettings_1.0.7_iphoneos-arm64.deb b/Releases/com.creaturecoding.tweaksettings_1.0.7_iphoneos-arm64.deb
new file mode 100644
index 0000000..af01ff5
Binary files /dev/null and b/Releases/com.creaturecoding.tweaksettings_1.0.7_iphoneos-arm64.deb differ
diff --git a/Resources/entitlements.plist b/Resources/entitlements.plist
index 240d4e5..6d2068d 100644
--- a/Resources/entitlements.plist
+++ b/Resources/entitlements.plist
@@ -36,6 +36,28 @@
com.apple.private.security.storage.AppDataContainers
+
+ com.apple.private.MobileContainerManager.allowed
+
+ com.apple.private.MobileContainerManager.otherIdLookup
+
+ com.apple.private.MobileContainerManager.otherIdentifierLookup
+
+ com.apple.private.MobileContainerManager.userManagedAssets
+
+
+ com.apple.springboard.opensensitiveurl
+
+ com.apple.springboard.presentPowerDownUI
+
+
+ com.apple.frontboard.delete-application-snapshots
+
+ com.apple.frontboard.shutdown
+
+ com.apple.frontboardservices.display-layout-monitor
+
+
com.apple.security.iokit-user-client-class
diff --git a/TweakSettings-App/NSTask.h b/TweakSettings-App/NSTask.h
new file mode 100644
index 0000000..d4e4551
--- /dev/null
+++ b/TweakSettings-App/NSTask.h
@@ -0,0 +1,66 @@
+#import
+
+@class NSString, NSArray, NSDictionary;
+
+@interface NSTask : NSObject
+
+// Create an NSTask which can be run at a later time
+// An NSTask can only be run once. Subsequent attempts to
+// run an NSTask will raise.
+// Upon task death a notification will be sent
+// { Name = NSTaskDidTerminateNotification; object = task; }
+//
+
+- (_Nullable instancetype)init;
+
+// set parameters
+// these methods can only be done before a launch
+// if not set, use current
+// if not set, use current
+
+// set standard I/O channels; may be either an NSFileHandle or an NSPipe
+- (void)setStandardInput:(id _Nullable)input;
+- (void)setStandardOutput:(id _Nullable)output;
+- (void)setStandardError:(id _Nullable)error;
+
+// get parameters
+@property (NS_NONATOMIC_IOSONLY, copy) NSString *_Nullable launchPath;
+@property (NS_NONATOMIC_IOSONLY, copy) NSArray *_Nullable arguments;
+@property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *_Nullable environment;
+@property (NS_NONATOMIC_IOSONLY, copy) NSString *_Nullable currentDirectoryPath;
+@property(NS_NONATOMIC_IOSONLY, copy) NSURL *_Nullable currentDirectoryURL;
+
+// get standard I/O channels; could be either an NSFileHandle or an NSPipe
+- (id _Nullable)standardInput;
+- (id _Nullable)standardOutput;
+- (id _Nullable)standardError;
+
+// actions
+- (void)launch;
+
+- (void)interrupt; // Not always possible. Sends SIGINT.
+- (void)terminate; // Not always possible. Sends SIGTERM.
+
+@property (NS_NONATOMIC_IOSONLY, readonly) BOOL suspend;
+@property (NS_NONATOMIC_IOSONLY, readonly) BOOL resume;
+
+// status
+@property (NS_NONATOMIC_IOSONLY, readonly) int processIdentifier;
+@property (NS_NONATOMIC_IOSONLY, getter = isRunning, readonly) BOOL running;
+
+@property (NS_NONATOMIC_IOSONLY, readonly) int terminationStatus;
+@property (copy, nonnull) void (^terminationHandler)(NSTask *_Nonnull);
+
+@end
+
+@interface NSTask (NSTaskConveniences)
+
++ (NSTask *_Nullable)launchedTaskWithLaunchPath:(NSString *_Nonnull)path arguments:(NSArray *_Nullable)arguments;
+// convenience; create and launch
+
+- (void)waitUntilExit;
+// poll the runLoop in defaultMode until task completes
+
+@end
+
+FOUNDATION_EXPORT NSString *_Nullable const NSTaskDidTerminateNotification;
\ No newline at end of file
diff --git a/TweakSettings-App/TS-Prefix.pch b/TweakSettings-App/TS-Prefix.pch
index a4b7169..8ccd668 100644
--- a/TweakSettings-App/TS-Prefix.pch
+++ b/TweakSettings-App/TS-Prefix.pch
@@ -73,19 +73,4 @@ NS_INLINE __unused NSArray *ARRAY_WITH_PLIST(NSString *path) {
return ARRAY_WITH_PLIST_OPTIONS(path, NSPropertyListImmutable);
}
-NS_INLINE __unused int STATUS_FOR_COMMAND(NSString *command) {
- FILE *proc = popen(command.UTF8String, "r");
-
- if (!proc) {return EXIT_FAILURE;}
-
- int size = 1024;
- char data[size];
-
- while (fgets(data, size, proc) != NULL) {}
-
- int status = pclose(proc);
-
- return status;
-}
-
#endif /* TS_Prefix_pch */
diff --git a/TweakSettings-App/TSOptionsController.m b/TweakSettings-App/TSOptionsController.m
index 59f17f4..309cb32 100644
--- a/TweakSettings-App/TSOptionsController.m
+++ b/TweakSettings-App/TSOptionsController.m
@@ -90,7 +90,7 @@ - (void)_openLink:(PSSpecifier *)specifier {
- (NSArray *)_footerSpecifiers {
PSSpecifier *developerGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
- [developerGroupSpecifier setProperty:@"CreatureCoding © 2021" forKey:PSFooterTextGroupKey];
+ [developerGroupSpecifier setProperty:@"CreatureCoding © 2023" forKey:PSFooterTextGroupKey];
[developerGroupSpecifier setProperty:@1 forKey:PSFooterAlignmentGroupKey];
PSSpecifier *changelogSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Changelog" target:self set:nil get:nil detail:TSChangelogController.class cell:PSLinkCell edit:nil];
diff --git a/TweakSettings-App/TSPackageUtility.m b/TweakSettings-App/TSPackageUtility.m
index 8cde3d9..43bf040 100644
--- a/TweakSettings-App/TSPackageUtility.m
+++ b/TweakSettings-App/TSPackageUtility.m
@@ -11,6 +11,7 @@
#import "TSPackageUtility.h"
#import "libprefs.h"
+#import "rootless.h"
#pragma mark - LIBPREFS Shim
@@ -36,9 +37,9 @@ BOOL PREFERENCE_FILTER_PASSES_ENVIRONMENT_CHECKS(NSDictionary *filter) {
if (isBundle) {
NSFileManager *fileManger = NSFileManager.defaultManager;
if (![fileManger fileExistsAtPath:bundlePath])
- bundlePath = [NSString stringWithFormat:@"/Library/PreferenceBundles/%@.bundle", bundleName];
+ bundlePath = [NSString stringWithFormat:ROOT_PATH_NS(@"/Library/PreferenceBundles/%@.bundle"), bundleName];
if (![fileManger fileExistsAtPath:bundlePath])
- bundlePath = [NSString stringWithFormat:@"/System/Library/PreferenceBundles/%@.bundle", bundleName];
+ bundlePath = [NSString stringWithFormat:ROOT_PATH_NS(@"/System/Library/PreferenceBundles/%@.bundle"), bundleName];
if (![fileManger fileExistsAtPath:bundlePath]) {
return nil;
}
@@ -91,14 +92,14 @@ @implementation TSPackageUtility {
+ (NSArray *)loadTweakSpecifiersInController:(PSListController *)controller {
NSMutableArray *preferenceSpecifiers = [NSMutableArray new];
- NSArray *preferenceBundlePaths = [NSFileManager.defaultManager subpathsOfDirectoryAtPath:@"/Library/PreferenceLoader/Preferences" error:nil];
+ NSArray *preferenceBundlePaths = [NSFileManager.defaultManager subpathsOfDirectoryAtPath:ROOT_PATH_NS(@"/Library/PreferenceLoader/Preferences") error:nil];
NSMutableArray *searchableItems = [NSMutableArray new];
for (NSString *item in preferenceBundlePaths)
{
if (![item.pathExtension isEqualToString:@"plist"]) continue;
- NSString *plistPath = [NSString stringWithFormat:@"/Library/PreferenceLoader/Preferences/%@", item];
+ NSString *plistPath = [NSString stringWithFormat:ROOT_PATH_NS(@"/Library/PreferenceLoader/Preferences/%@"), item];
NSDictionary *plist = DICTIONARY_WITH_PLIST(plistPath);
if (!plist[@"entry"]) continue;
@@ -107,8 +108,8 @@ @implementation TSPackageUtility {
NSString *bundlePath = [plistPath stringByDeletingLastPathComponent];
NSString *title = [item.lastPathComponent stringByDeletingPathExtension];
- BOOL customInstall = access("/var/lib/dpkg/info/com.artikus.preferenceloader.list", F_OK) == 0
- || access("/var/lib/dpkg/info/com.creaturecoding.preferred.list", F_OK) == 0;
+ BOOL customInstall = access(ROOT_PATH("/var/lib/dpkg/info/com.artikus.preferenceloader.list"), F_OK) == 0
+ || access(ROOT_PATH("/var/lib/dpkg/info/com.creaturecoding.preferred.list"), F_OK) == 0;
NSArray *itemSpecifiers = !customInstall
? SPECIFIERS_FROM_ENTRY(plist[@"entry"], bundlePath, title, controller)
@@ -123,7 +124,7 @@ @implementation TSPackageUtility {
[specifier setProperty:[UIImage imageNamed:@"tweak"] forKey:PSIconImageKey];
}
- CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *) kUTTypeImage];
+ CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] init];
attributeSet.title = specifier.name;
attributeSet.contentDescription = [NSString stringWithFormat:@"Tweak Settings \u2192 %@", specifier.name];
attributeSet.thumbnailData = UIImagePNGRepresentation([specifier propertyForKey:PSIconImageKey]);
diff --git a/TweakSettings-App/TSUtilityActionManager.h b/TweakSettings-App/TSUtilityActionManager.h
index 54c4014..1653a38 100644
--- a/TweakSettings-App/TSUtilityActionManager.h
+++ b/TweakSettings-App/TSUtilityActionManager.h
@@ -12,6 +12,12 @@
@class UIAlertController;
@class UIAlertAction;
+struct TaskResult {
+ int status;
+ __strong NSString *output;
+ __strong NSString *error;
+};
+
extern NSString *const TSActionTypeRespring;
extern NSString *const TSActionTypeSafemode;
extern NSString *const TSActionTypeUICache;
@@ -20,6 +26,7 @@ extern NSString *const TSActionTypeReboot;
extern NSString *const TSActionTypeUserspaceReboot;
extern NSString *const TSActionTypeTweakInject;
+extern struct TaskResult ExecuteCommand(NSString *command);
extern NSString *TitleForActionType(NSString *type);
extern NSString *SubtitleForActionType(NSString *type);
extern BOOL CanRunWithoutConfirmation(NSString *actionType);
@@ -27,5 +34,6 @@ extern int HandleActionForType(NSString *actionType);
extern UIAlertController *ActionAlertForType(NSString *actionType);
extern UIAlertController *ActionListAlert(void);
extern UIMenu *ActionListMenu(void) API_AVAILABLE(ios(13.0));
+extern NSString *CommandForActionType(NSString *actionType);
#endif /* TSActionType_h */
diff --git a/TweakSettings-App/TSUtilityActionManager.m b/TweakSettings-App/TSUtilityActionManager.m
index 7ba3c5d..b2cf39b 100644
--- a/TweakSettings-App/TSUtilityActionManager.m
+++ b/TweakSettings-App/TSUtilityActionManager.m
@@ -10,6 +10,8 @@
#import "TSUtilityActionManager.h"
#import "Localizable.h"
#import "TSAppDelegate.h"
+#import "rootless.h"
+#import "NSTask.h"
NSString *const TSActionTypeRespring = @"respring";
NSString *const TSActionTypeSafemode = @"safemode";
@@ -19,6 +21,50 @@
NSString *const TSActionTypeUserspaceReboot = @"usreboot";
NSString *const TSActionTypeTweakInject = @"tweakinject";
+struct TaskResult ExecuteCommand(NSString *command) {
+ NSTask *task = [[NSTask alloc] init];
+ [task setLaunchPath:ROOT_PATH_NS(@"/bin/sh")];
+ [task setArguments:@[@"-c", command]];
+
+ NSPipe *outputPipe = [NSPipe pipe];
+ [task setStandardOutput:outputPipe];
+
+ NSPipe *errorPipe = [NSPipe pipe];
+ [task setStandardError:errorPipe];
+
+ [task launch];
+ [task waitUntilExit];
+
+ NSData *errorData;
+ NSData *outputData;
+ NSString *output;
+ NSString *error;
+
+ if (@available(iOS 13.0, *)) {
+ outputData = [[[task standardOutput] fileHandleForReading] readDataToEndOfFileAndReturnError:nil];
+ errorData = [[[task standardError] fileHandleForReading] readDataToEndOfFileAndReturnError:nil];
+ } else {
+ outputData = [[[task standardOutput] fileHandleForReading] readDataToEndOfFile];
+ errorData = [[[task standardError] fileHandleForReading] readDataToEndOfFile];
+ }
+
+ if (outputData && outputData.length > 0) {
+ output = [[NSString alloc] initWithData:outputData encoding:NSASCIIStringEncoding];
+ }
+
+ if (errorData && errorData.length > 0) {
+ error = [[NSString alloc] initWithData:errorData encoding:NSASCIIStringEncoding];
+ NSLog(@"TweakSettings: TASK INPUT: %@ ERROR: %@, STATUS: %d", task.arguments.lastObject, error, task.terminationStatus);
+ }
+
+ struct TaskResult result;
+ result.status = task.terminationStatus;
+ result.output = output;
+ result.error = error;
+
+ return result;
+}
+
NSString *TitleForActionType(NSString *type) {
if ([type isEqualToString:TSActionTypeRespring]) return NSLocalizedString(RESPRING_TITLE_KEY, nil);
if ([type isEqualToString:TSActionTypeSafemode]) return NSLocalizedString(SAFEMODE_TITLE_KEY, nil);
@@ -53,16 +99,7 @@ int HandleActionForType(NSString *actionType) {
if (!actionType || !actionType.length) return EXIT_FAILURE;
- int status = STATUS_FOR_COMMAND([NSString stringWithFormat:@"/usr/bin/tweaksettings-utility --%@", actionType]);
- if (status == EXIT_SUCCESS && [actionType isEqualToString:TSActionTypeTweakInject]) {
- if (access("/etc/rc.d/substrate", F_OK) == 0) {
- if (STATUS_FOR_COMMAND(@"/usr/bin/tweaksettings-utility --substrated") == EXIT_SUCCESS) {
- STATUS_FOR_COMMAND(@"/usr/bin/tweaksettings-utility --respring");
- }
- } else {
- STATUS_FOR_COMMAND(@"/usr/bin/tweaksettings-utility --respring");
- }
- }
+ int status = ExecuteCommand(CommandForActionType(actionType)).status;
return status;
}
@@ -83,7 +120,7 @@ int HandleActionForType(NSString *actionType) {
UIAlertController *ActionListAlert(void) {
- BOOL userspace_supported = access("/odyssey/jailbreakd.plist", F_OK) == 0 || access("/taurine/jailbreakd.plist", F_OK) == 0;
+ BOOL userspace_supported = access(ROOT_PATH("/odyssey/jailbreakd.plist"), F_OK) == 0 || access(ROOT_PATH("/taurine/jailbreakd.plist"), F_OK) == 0;
UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(RESPRING_TITLE_KEY, nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
@@ -117,7 +154,10 @@ int HandleActionForType(NSString *actionType) {
UIMenu *ActionListMenu(void) API_AVAILABLE(ios(13.0)) {
NSMutableArray *menuActions = [NSMutableArray new];
- BOOL userspace_supported = access("/odyssey/jailbreakd.plist", F_OK) == 0 || access("/taurine/jailbreakd.plist", F_OK) == 0;
+ BOOL userspace_supported =
+ access(ROOT_PATH("/odyssey/jailbreakd.plist"), F_OK) == 0 ||
+ access(ROOT_PATH("/taurine/jailbreakd.plist"), F_OK) == 0 ||
+ access(ROOT_PATH("/.installed_dopamine"), F_OK) == 0;
[menuActions addObject:[UIAction actionWithTitle:NSLocalizedString(RESPRING_TITLE_KEY, nil) image:nil identifier:nil handler:^(__kindof UIAction *action) {
[APP_DELEGATE handleActionForType:TSActionTypeRespring];
@@ -144,4 +184,8 @@ int HandleActionForType(NSString *actionType) {
}]];
return [UIMenu menuWithTitle:@"" children:menuActions];
+}
+
+NSString *CommandForActionType(NSString *actionType) {
+ return [NSString stringWithFormat:ROOT_PATH_NS(@"/usr/bin/tweaksettings-utility --%@"), actionType];
}
\ No newline at end of file
diff --git a/TweakSettings-App/main.m b/TweakSettings-App/main.m
index f6a8030..1459d79 100644
--- a/TweakSettings-App/main.m
+++ b/TweakSettings-App/main.m
@@ -10,6 +10,7 @@
#import
#import "TSAppDelegate.h"
+#import "rootless.h"
int main(int argc, char *argv[]) {
@@ -21,10 +22,10 @@ int main(int argc, char *argv[]) {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([TSAppDelegate class]);
- NSArray *librariesToLoad = ARRAY_WITH_PLIST(@"/Applications/TweakSettings.app/libraries.plist");
+ NSArray *librariesToLoad = ARRAY_WITH_PLIST(ROOT_PATH_NS(@"/Applications/TweakSettings.app/libraries.plist"));
for (NSString *path in librariesToLoad) {
- dlopen(path.UTF8String, RTLD_NOW);
+ dlopen(ROOT_PATH_NS_VAR(path).UTF8String, RTLD_NOW);
}
}
diff --git a/TweakSettings-App/rootless.h b/TweakSettings-App/rootless.h
new file mode 100644
index 0000000..30733f2
--- /dev/null
+++ b/TweakSettings-App/rootless.h
@@ -0,0 +1,11 @@
+#ifdef THEOS_PACKAGE_INSTALL_PREFIX
+#define ROOT_PATH(cPath) THEOS_PACKAGE_INSTALL_PREFIX cPath
+#define ROOT_PATH_NS(path) @THEOS_PACKAGE_INSTALL_PREFIX path
+#define ROOT_PATH_NS_VAR(path) [@THEOS_PACKAGE_INSTALL_PREFIX stringByAppendingPathComponent:path]
+#define ROOT_PATH_VAR(cPath) ROOT_PATH_NS_VAR(@cPath).fileSystemRepresentation
+#else
+#define ROOT_PATH(cPath) cPath
+#define ROOT_PATH_NS(path) path
+#define ROOT_PATH_NS_VAR(path) path
+#define ROOT_PATH_VAR(cPath) cPath
+#endif
diff --git a/TweakSettings-Utility/Makefile b/TweakSettings-Utility/Makefile
index a1acc80..2f51e48 100644
--- a/TweakSettings-Utility/Makefile
+++ b/TweakSettings-Utility/Makefile
@@ -1,9 +1,12 @@
include $(THEOS)/makefiles/common.mk
-PREFIX = $(THEOS)/toolchains/xcode11.xctoolchain/usr/bin/
TOOL_NAME = tweaksettings-utility
tweaksettings-utility_FILES = main.c
+tweaksettings-utility_CFLAGS = -fobjc-arc
TARGET_CODESIGN_FLAGS = "-Sentitlements.plist"
-include $(THEOS_MAKE_PATH)/tool.mk
\ No newline at end of file
+include $(THEOS_MAKE_PATH)/tool.mk
+
+before-package::
+ chmod +s $(THEOS_STAGING_DIR)/usr/bin/tweaksettings-utility
\ No newline at end of file
diff --git a/TweakSettings-Utility/main.c b/TweakSettings-Utility/main.c
index 6e8afdd..4cdd6d7 100644
--- a/TweakSettings-Utility/main.c
+++ b/TweakSettings-Utility/main.c
@@ -6,6 +6,9 @@
#include
#include
+#import "rootless.h"
+#include
+
int proc_pidpath(pid_t pid, void *buffer, uint32_t buffersize);
typedef enum {
@@ -66,11 +69,30 @@ int status_for_cmd(const char *cmd) {
return pclose(proc);
}
+int check_fork(pid_t pid) {
+ if (pid != 0) {
+ printf("tweaksettings-utility fork error (%s) (%d),\n", strerror(errno), errno);
+ }
+
+ return pid;
+}
+
+int wait_pid(pid_t pid) {
+ int wait;
+ int status;
+ if ((wait = waitpid (pid, &status, 0)) == -1)
+ printf("tweaksettings-utility wait error (%s) (%d),\n", strerror(errno), errno);
+ if (wait == pid) {
+ return 0;
+ }
+ return -1;
+}
+
int main(int argc, char **argv, char **envp) {
// check that TweakSettings.app exists
struct stat correct;
- if (lstat("/Applications/TweakSettings.app/TweakSettings", &correct) == -1){
+ if (lstat(ROOT_PATH("/Applications/TweakSettings.app/TweakSettings"), &correct) == -1){
printf("tweaksettings-utility can only be used by TweakSettings.app,\n");
return EX_NOPERM;
}
@@ -82,7 +104,7 @@ int main(int argc, char **argv, char **envp) {
char buffer[(1024)] = {0};
int pidpath = proc_pidpath(parent, buffer, sizeof(buffer));
if (pidpath > 0){
- if (strcmp(buffer, "/Applications/TweakSettings.app/TweakSettings") == 0){
+ if (strcmp(buffer, ROOT_PATH("/Applications/TweakSettings.app/TweakSettings")) == 0){
tweaksettings = true;
}
}
@@ -138,43 +160,72 @@ int main(int argc, char **argv, char **envp) {
print_usage();
} break;
case TSUtilityActionTypeRespring: {
- execlp("/usr/bin/killall", "killall", "backboardd", NULL);
+ status = execl(ROOT_PATH("/usr/bin/killall"), "killall", "backboardd", NULL);
} break;
case TSUtilityActionTypeSafemode: {
- execlp("/usr/bin/killall", "killall", "-SEGV", "SpringBoard", NULL);
+ status = execl(ROOT_PATH("/usr/bin/killall"), "killall", "-SEGV", "SpringBoard", NULL);
} break;
case TSUtilityActionTypeUICache: {
- execlp("/usr/bin/uicache", "uicache", NULL);
+ status = execl(ROOT_PATH("/usr/bin/uicache"), "uicache", NULL);
} break;
case TSUtilityActionTypeReboot: {
- execlp("/usr/sbin/reboot", "reboot", NULL);
+ status = execl(ROOT_PATH("/usr/sbin/reboot"), "reboot", NULL);
} break;
case TSUtilityActionTypeLDRestart: {
- execlp("/usr/bin/ldrestart", "ldrestart", NULL);
+ status = execl(ROOT_PATH("/usr/bin/ldrestart"), "ldrestart", NULL);
} break;
case TSUtilityActionTypeUSReboot: {
- status = status_for_cmd("/usr/bin/launchctl reboot userspace");
+ status = execl(ROOT_PATH("/usr/bin/launchctl"), "launchctl", "reboot", "userspace", NULL);
} break;
case TSUtilityActionTypeTweakinject: {
+ if (access("/var/jb/.installed_dopamine", F_OK) == 0) {
+ pid_t cpid = fork();
+ if (cpid == 0) {
+ status = access("/var/jb/basebin/.safe_mode", F_OK) == 0
+ ? execl(ROOT_PATH("/bin/rm"), "rm", "-f", "/var/jb/basebin/.safe_mode", NULL)
+ : execl(ROOT_PATH("/bin/touch"), "touch", "/var/jb/basebin/.safe_mode", NULL);
+ }
+
+ if (wait_pid(cpid) == 0) {
+ status = execl(ROOT_PATH("/usr/bin/launchctl"), "launchctl", "reboot", "userspace", NULL);
+ }
+ } else if (access(ROOT_PATH("/usr/lib/TweakInject.dylib"), F_OK) == 0) {
+ pid_t cpid = fork();
+
+ if (cpid == 0) {
+ status = access(ROOT_PATH("/.disable_tweakinject"), F_OK) == 0
+ ? execl(ROOT_PATH("/bin/rm"), "rm", "-f", ROOT_PATH("/.disable_tweakinject"), NULL)
+ : execl(ROOT_PATH("/bin/touch"), "touch", ROOT_PATH("/.disable_tweakinject"), NULL);
+ }
+
+ if (wait_pid(cpid) == 0) {
+ status = execl(ROOT_PATH("/usr/bin/killall"), "killall", "backboardd", NULL);
+ }
+ } else {
+ pid_t cpid = fork();
- if (access("/usr/lib/TweakInject.dylib", F_OK) == 0) {
+ if (cpid == 0) {
+ status = access(ROOT_PATH("/var/tmp/.substrated_disable_loader"), F_OK) == 0
+ ? execl(ROOT_PATH("/bin/rm"), "rm", "-f", ROOT_PATH("/var/tmp/.substrated_disable_loader"), NULL)
+ : execl(ROOT_PATH("/bin/touch"), "touch", ROOT_PATH("/var/tmp/.substrated_disable_loader"), NULL);
+ }
- if (access("/.disable_tweakinject", F_OK) == 0) {
- execlp("/bin/rm", "rm", "-f", "/.disable_tweakinject", NULL);
- } else {
- execlp("/bin/touch", "touch", "/.disable_tweakinject", NULL);
- }
- } else {
- if (access("/var/tmp/.substrated_disable_loader", F_OK) == 0) {
- execlp("/bin/rm", "rm", "-f", "/var/tmp/.substrated_disable_loader", NULL);
- } else {
- execlp("/bin/touch", "touch", "/var/tmp/.substrated_disable_loader", NULL);
- }
+ if (wait_pid(cpid) == 0) {
+ cpid = fork();
+
+ if (cpid == 0) {
+ status = execl(ROOT_PATH("/etc/rc.d/substrate"), "substrate", NULL);
+ }
+
+ if (wait_pid(cpid) == 0) {
+ status = execl(ROOT_PATH("/usr/bin/killall"), "killall", "backboardd", NULL);
+ }
+ }
}
} break;
case TSUtilityActionTypeSubstrated: {
if (access("/etc/rc.d/substrate", F_OK) == 0) {
- execlp("/etc/rc.d/substrate", "substrate", NULL);
+ execl("/etc/rc.d/substrate", "substrate", NULL);
}
} break;
}
diff --git a/TweakSettings.xcodeproj/project.pbxproj b/TweakSettings.xcodeproj/project.pbxproj
index 03c0368..dced1ec 100644
--- a/TweakSettings.xcodeproj/project.pbxproj
+++ b/TweakSettings.xcodeproj/project.pbxproj
@@ -22,9 +22,9 @@
9B241E2F90DD7CBD64A43B51 /* TSSearchableListController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B241E51979762427B0DEF19 /* TSSearchableListController.m */; };
9B241FBC80A9F03FB421F1D3 /* TSOptionsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B241D3DD023C428A7AD45EF /* TSOptionsController.m */; };
9B241FDA50F976918DC53162 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9B241DE01047656B78369A94 /* LaunchScreen.storyboard */; };
+ B80B985A2A06E70E00C440EB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B871CDB5265991710058F1C2 /* Localizable.strings */; };
B86FC5D626645DE60011E4AF /* Preferences.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B871CD462651D3680058F1C2 /* Preferences.framework */; };
B871CDA0265601110058F1C2 /* icon_large.png in Resources */ = {isa = PBXBuildFile; fileRef = B871CD9F265601110058F1C2 /* icon_large.png */; };
- B871CDBA26599BFD0058F1C2 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B871CDB5265991710058F1C2 /* Localizable.strings */; };
B8917F68267590B700A9DA57 /* CoreSpotlight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8917F67267590B700A9DA57 /* CoreSpotlight.framework */; };
B8917F6A2675944E00A9DA57 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8917F692675944E00A9DA57 /* CoreServices.framework */; };
/* End PBXBuildFile section */
@@ -34,6 +34,7 @@
9B241145674E6322664B2C03 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
9B2411C5CDD06E84A912DF3A /* libprefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libprefs.h; sourceTree = ""; };
9B24127C70ECB51EAE77F9EE /* TSPackageUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSPackageUtility.h; sourceTree = ""; };
+ 9B2412872ABBBB036129F433 /* build.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = ""; };
9B2413E3DE3004D22E25AAFB /* TSRootListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRootListController.m; sourceTree = ""; };
9B2413E6B518A0A99C895507 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
9B24142E08BDFAEE4F8373EF /* TSChangelogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSChangelogController.h; sourceTree = ""; };
@@ -44,9 +45,11 @@
9B24169943CD9A7E1AA8E2FE /* TSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TSAppDelegate.h; sourceTree = ""; };
9B2416D9FECD758BFA318498 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.info; path = Info.plist; sourceTree = ""; };
9B24181BB83D9773FE8446BB /* TSPrefsRootController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSPrefsRootController.h; sourceTree = ""; };
+ 9B241824397C45F85F933DC1 /* rootless.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rootless.h; sourceTree = ""; };
9B24192FDF28BB2496BBEA7B /* TSUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSUserDefaults.m; sourceTree = ""; };
9B2419707513EEC97C39BA0C /* TSSplitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSplitViewController.m; sourceTree = ""; };
9B2419CD47CC813402F66384 /* Localizable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Localizable.h; sourceTree = ""; };
+ 9B241A100BBAE284CD214164 /* NSTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSTask.h; sourceTree = ""; };
9B241B6A5EF71185ECED8986 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
9B241B6FA0ACC48629D31472 /* TSUtilityActionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSUtilityActionManager.h; sourceTree = ""; };
9B241BDCA3396202FEB00F19 /* TSRootListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRootListController.h; sourceTree = ""; };
@@ -99,6 +102,7 @@
9B241880696EB372AB810EDA /* Products */,
9B2416070FA2791AF62D5143 /* TweakSettings-App */,
B86FC5D226645DC50011E4AF /* Frameworks */,
+ 9B2412872ABBBB036129F433 /* build.sh */,
);
sourceTree = "";
};
@@ -136,6 +140,8 @@
9B241649FFFF894DC1194290 /* TSUtilityActionManager.m */,
9B241C07A10B2F57EE3E6BDE /* TSChangelogController.m */,
9B24142E08BDFAEE4F8373EF /* TSChangelogController.h */,
+ 9B241824397C45F85F933DC1 /* rootless.h */,
+ 9B241A100BBAE284CD214164 /* NSTask.h */,
);
path = "TweakSettings-App";
sourceTree = "";
@@ -259,7 +265,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- B871CDBA26599BFD0058F1C2 /* Localizable.strings in Resources */,
+ B80B985A2A06E70E00C440EB /* Localizable.strings in Resources */,
B871CDA0265601110058F1C2 /* icon_large.png in Resources */,
9B2417125AF333AF7433AE3F /* Assets.xcassets in Resources */,
9B241FDA50F976918DC53162 /* LaunchScreen.storyboard in Resources */,
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..dc96f60
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,15 @@
+#/bin/sh
+
+sudo xcode-select -switch /Applications/Xcode-11.7.0.app/Contents/Developer
+xcode-select --print-path
+# export PREFIX=$THEOS/toolchains/Xcode11.xctoolchain/usr/bin/
+
+make clean
+make package FINALPACKAGE=1
+
+# export -n PREFIX
+sudo xcode-select -switch /Applications/Xcode-12.5.0.app/Contents/Developer
+xcode-select --print-path
+
+make clean
+make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless
\ No newline at end of file
diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control
index cf9cc6f..d1478e3 100644
--- a/layout/DEBIAN/control
+++ b/layout/DEBIAN/control
@@ -1,7 +1,7 @@
Package: com.creaturecoding.tweaksettings
Name: TweakSettings
Depends: firmware (>= 10.0), preferenceloader | com.creaturecoding.preferred
-Version: 1.0.6
+Version: 1.0.7
Priority: optional
Architecture: iphoneos-arm
Description: Dedicated settings app for tweaks
diff --git a/layout/DEBIAN/postinst b/layout/DEBIAN/postinst
index 87a669e..e5256fd 100755
--- a/layout/DEBIAN/postinst
+++ b/layout/DEBIAN/postinst
@@ -1,12 +1,35 @@
#!/bin/sh
-chown root:wheel /usr/bin/tweaksettings-utility
-chmod 0777 /usr/bin/tweaksettings-utility
-chmod +s /usr/bin/tweaksettings-utility
+UTILITY=/usr/bin/tweaksettings-utility
+# if tweaksettings-utility doesnt exist, try the rootless path
+if [ ! -f "$UTILITY" ]; then
+ UTILITY=/var/jb$UTILITY
+fi
-chown root:wheel /Applications/TweakSettings.app/TweakSettings
-chmod 0755 /Applications/TweakSettings.app/TweakSettings
+if [ -f "$UTILITY" ]; then
+ chown root:wheel $UTILITY
+ chmod 0777 $UTILITY
+ chmod +s $UTILITY
+ echo "set $UTILITY permissions"
+fi
-uicache -p /Applications/TweakSettings.app
+APP=/Applications/TweakSettings.app/TweakSettings
+# if TweakSettings.app doesnt exist, try the rootless path
+if [ ! -f "$APP" ]; then
+ APP=/var/jb$APP
+fi
+
+if [ -f "$APP" ]; then
+ chown root:wheel $APP
+ chmod 0755 $APP
+ echo "set $APP permissions"
+fi
+
+APP_FOLDER=${APP%/*}
+
+if [ -f "$APP_FOLDER" ]; then
+ uicache -p APP_FOLDER
+ echo $APP_FOLDER
+fi
exit 0;