123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707 |
- /* UIKit Tools - command-line utilities for UIKit
- * Copyright (C) 2018-2019 Sam Bingner
- * Copyright (C) 2008-2012 Jay Freeman (saurik)
- * Portions Copyright (C) 2019 Sam Bingner
- */
- /* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- /* Modified BSD License {{{ */
- /*
- * Redistribution and use in source and binary
- * forms, with or without modification, are permitted
- * provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the
- * above copyright notice, this list of conditions
- * and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions
- * and the following disclaimer in the documentation
- * and/or other materials provided with the
- * distribution.
- * 3. The name of the author may not be used to endorse
- * or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /* }}} */
- #import <Foundation/Foundation.h>
- #import "NSTask.h"
- #import <dlfcn.h>
- #import <notify.h>
- #import <sys/types.h>
- #import <sys/stat.h>
- #import <unistd.h>
- #import <getopt.h>
- #import <launch.h>
- #import <objc/runtime.h>
- #import <crt_externs.h>
- #import <xpc/xpc.h>
- #include <spawn.h>
- #include <sys/wait.h>
- #include "csstore.hpp"
- @interface PBSSystemService : NSObject
- +(id)sharedInstance;
- -(void)relaunchBackboardd;
- @end
- @interface PBSSystemServiceConnection : NSObject
- +(id)sharedConnection;
- -(id)systemServiceProxy;
- @end
- @interface NSMutableArray (Cydia)
- - (void) addInfoDictionary:(NSDictionary *)info;
- @end
- @implementation NSMutableArray (Cydia)
- - (void) addInfoDictionary:(NSDictionary *)info {
- [self addObject:info];
- }
- - (NSArray *) allInfoDictionaries {
- return self;
- }
- @end
- @interface NSMutableDictionary (Cydia)
- - (void) addInfoDictionary:(NSDictionary *)info;
- @end
- @implementation NSMutableDictionary (Cydia)
- - (void) addInfoDictionary:(NSDictionary *)info {
- NSString *bundle = [info objectForKey:@"CFBundleIdentifier"];
- [self setObject:info forKey:bundle];
- }
- - (NSArray *) allInfoDictionaries {
- return [self allValues];
- }
- @end
- @interface LSApplicationProxy : NSObject
- - (NSString*) applicationIdentifier;
- - (NSURL*) bundleURL;
- - (NSDate*) registeredDate;
- @end
- @interface LSApplicationWorkspace : NSObject
- + (id) defaultWorkspace;
- - (BOOL) registerApplication:(id)application;
- - (BOOL) unregisterApplication:(id)application;
- - (BOOL) invalidateIconCache:(id)bundle;
- - (BOOL) registerApplicationDictionary:(id)application;
- - (BOOL) installApplication:(id)application withOptions:(id)options;
- - (BOOL) _LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)system internal:(BOOL)internal user:(BOOL)user;
- - (NSArray<LSApplicationProxy*>*) allApplications;
- @end
- @interface MCMAppDataContainer
- +(id)containerWithIdentifier:(NSString*)identifier createIfNecessary:(bool)create existed:(bool*)existed error:(NSError*)error;
- -(NSURL*)url;
- @end
- @interface FBSSystemService
- +(id)sharedService;
- -(void)sendActions:(NSSet*)actions withResult:(id)result;
- @end
- typedef enum {
- None = 0,
- RestartRenderServer = (1 << 0), // also relaunch backboardd
- SnapshotTransition = (1 << 1),
- FadeToBlackTransition = (1 << 2),
- } SBSRelaunchActionStyle;
- @interface SBSRelaunchAction
- +(id)actionWithReason:(id)reason options:(int64_t)options targetURL:(NSURL*)url;
- @end
- static int verbose=0;
- static int standard_uicache(void);
- static Class $MCMPluginKitPluginDataContainer;
- static Class $MCMAppDataContainer;
- static Class $LSApplicationWorkspace;
- LSApplicationWorkspace *workspace=nil;
- extern char **environ;
- int my_system(const char *cmd) {
- pid_t pid;
- char *argv[] = {"sh", "-c", (char*)cmd, NULL};
- int status;
- fprintf(stderr, "Run command: %s\n", cmd);
- status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);
- if (status == 0) {
- printf("Child pid: %i\n", pid);
- if (waitpid(pid, &status, 0) != -1) {
- printf("Child exited with status %i\n", status);
-
- } else {
- perror("waitpid");
- }
- } else {
- printf("posix_spawn: %s\n", strerror(status));
- }
- return status;
- }
- NSString *getAppPath(NSString *path)
- {
- path = [path stringByResolvingSymlinksInPath];
- if (![path hasPrefix:@"/Applications/"]) {
- fprintf(stderr, "Error: Path must be within /Applications/\n");
- return nil;
- }
- return [NSString pathWithComponents:[[path pathComponents] subarrayWithRange:NSMakeRange(0, 3)]];
- }
- bool appIsRegistered(NSString *path)
- {
- @autoreleasepool {
- path = getAppPath(path);
- if (!path) return false;
- for (LSApplicationProxy *app in [workspace allApplications]) {
- if ([path isEqualToString:[[app bundleURL] path]]) return true;
- }
- return false;
- }
- }
- bool unregisterPath(NSString *path)
- {
- @autoreleasepool {
- if (verbose) fprintf(stderr, "Unregistering %s\n", path.lastPathComponent.UTF8String);
- path = getAppPath(path);
- if (!path) return false;
- if (appIsRegistered(path) && ![workspace unregisterApplication:[NSURL fileURLWithPath:path]]) {
- fprintf(stderr, "Error: unregisterApplication failed for %s\n", path.lastPathComponent.UTF8String);
- return false;
- }
- }
- return true;
- }
- // Credit to coolstar for finding how to do this and not sharing with the community thereby forcing me to figure out how to do the same thing.
- bool registerPath(NSString *path)
- {
- if (!path) {
- if (verbose) fprintf(stderr, "registerPath called with no path\n");
- return false;
- }
- NSString *realPath = getAppPath(path);
- if (!realPath) {
- if (verbose) fprintf(stderr, "unable to determine path for %s\n", path.UTF8String);
- return false;
- }
- NSDictionary *infoDictionary = [NSDictionary dictionaryWithContentsOfFile:
- [realPath stringByAppendingPathComponent:@"Info.plist"]];
- NSString *bundleID = [infoDictionary objectForKey:@"CFBundleIdentifier"];
- if (bundleID) {
- NSFileManager *fm = [NSFileManager defaultManager];
- if ([infoDictionary objectForKey:@"CFBundleExecutable"]) {
- NSString *executable = [realPath stringByAppendingPathComponent:[infoDictionary objectForKey:@"CFBundleExecutable"]];
- if (![fm fileExistsAtPath:executable]) {
- fprintf(stderr, "Error: CFBundleExecutable defined but missing for %s - this is a fatal error. Aborting.\n", realPath.lastPathComponent.UTF8String);
- return false;
- }
- }
- NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- @"System", @"ApplicationType",
- @YES, @"BundleNameIsLocalized",
- bundleID, @"CFBundleIdentifier",
- @NO, @"CompatibilityState",
- @NO, @"IsDeletable",
- realPath, @"Path",
- [NSMutableDictionary dictionary], @"_LSBundlePlugins",
- nil];
- id appContainer = [$MCMAppDataContainer containerWithIdentifier:bundleID
- createIfNecessary:YES existed:NULL error:nil];
- NSString *appContainerPath = [[appContainer url] path];
- if (appContainerPath) {
- dict[@"Container"] = appContainerPath;
- }
- NSString *pluginsPath = [realPath stringByAppendingPathComponent:@"PlugIns"];
- for (NSString *plugin in [fm contentsOfDirectoryAtPath:pluginsPath error:nil]) {
- NSString *pluginPath = [pluginsPath stringByAppendingPathComponent:plugin];
- NSString *pluginInfoPlistPath = [pluginPath stringByAppendingPathComponent:@"Info.plist"];
- NSString *pluginBundleIdentifier = [[NSDictionary dictionaryWithContentsOfFile:pluginInfoPlistPath] objectForKey:@"CFBundleIdentifier"];
- if (pluginBundleIdentifier) {
- id pluginContainer = [$MCMPluginKitPluginDataContainer containerWithIdentifier:pluginBundleIdentifier
- createIfNecessary:YES existed:NULL error:nil];
- NSURL *pluginContainerURL = [pluginContainer url];
- NSString *pluginContainerPath = [pluginContainerURL path];
- dict[@"_LSBundlePlugins"][pluginBundleIdentifier] = @{
- @"ApplicationType": @"PluginKitPlugin",
- @"BundleNameIsLocalized": @YES,
- @"CFBundleIdentifier": pluginBundleIdentifier,
- @"CompatibilityState": @NO,
- @"Container": pluginContainerPath,
- @"Path": pluginPath,
- @"PluginOwnerBundleID": bundleID
- };
- }
- }
- if (![[$LSApplicationWorkspace defaultWorkspace] registerApplicationDictionary:dict]) {
- fprintf(stderr, "Error: registerApplicationDictionary failed for %s\n", path.lastPathComponent.UTF8String);
- return false;
- }
- } else {
- return unregisterPath(realPath);
- }
- return true;
- }
- void usage(void)
- {
- fprintf(stderr, "Usage: %s [-hrv] [[-p | -u] /Applications/App.app]]\n", getprogname());
- exit(EXIT_FAILURE);
- }
- pid_t launch_get_job_pid(const char * job)
- {
- launch_data_t resp;
- launch_data_t msg;
-
- msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
- if (msg == NULL) {
- return -1;
- }
-
- launch_data_dict_insert(msg, launch_data_new_string(job), LAUNCH_KEY_GETJOB);
-
- resp = launch_msg(msg);
- launch_data_free(msg);
-
- if (resp == NULL) {
- return -1;
- }
-
- if (launch_data_get_type(resp) != LAUNCH_DATA_DICTIONARY) return -1;
-
- launch_data_t pid_data = launch_data_dict_lookup(resp, "PID");
- if (launch_data_get_type(pid_data) != LAUNCH_DATA_INTEGER) return -1;
-
- pid_t pid = (pid_t)launch_data_get_integer(pid_data);
- launch_data_free(resp);
- return pid;
- }
- int standard_uicache(void)
- {
- @autoreleasepool {
- if (kCFCoreFoundationVersionNumber > 1000 && // this API is on iOS 7 but invaliding the icon cache is harder there
- [workspace respondsToSelector:@selector(_LSPrivateRebuildApplicationDatabasesForSystemApps:internal:user:)]) {
- if (![workspace _LSPrivateRebuildApplicationDatabasesForSystemApps:YES internal:YES user:NO])
- fprintf(stderr, "failed to rebuild application databases");
- return 0;
- }
- bool respring(false);
- NSString *home(NSHomeDirectory());
- NSString *path([NSString stringWithFormat:@"%@/Library/Caches/com.apple.mobile.installation.plist", home]);
- my_system("killall -SIGSTOP SpringBoard");
- sleep(1);
- @try {
- DeleteCSStores([home UTF8String]);
- my_system("killall lsd");
- if ([workspace respondsToSelector:@selector(invalidateIconCache:)])
- while (![workspace invalidateIconCache:nil])
- sleep(1);
- if (NSMutableDictionary *cache = [NSMutableDictionary dictionaryWithContentsOfFile:path]) {
- NSFileManager *manager = [NSFileManager defaultManager];
- NSError *error = nil;
- NSMutableDictionary *bundles([NSMutableDictionary dictionaryWithCapacity:16]);
- id after = [cache objectForKey:@"System"];
- if (after == nil) { error:
- fprintf(stderr, "%s\n", error == nil ? strerror(errno) : [[error localizedDescription] UTF8String]);
- goto cached;
- }
- id before([[after copy] autorelease]);
- [after removeAllObjects];
- NSArray *cached([cache objectForKey:@"InfoPlistCachedKeys"]);
- NSMutableSet *removed([NSMutableSet set]);
- for (NSDictionary *info in [before allInfoDictionaries])
- if (NSString *path = [info objectForKey:@"Path"])
- [removed addObject:path];
- if (NSArray *apps = [manager contentsOfDirectoryAtPath:@"/Applications" error:&error]) {
- for (NSString *app in apps)
- if ([app hasSuffix:@".app"]) {
- NSString *path = [@"/Applications" stringByAppendingPathComponent:app];
- NSString *plist = [path stringByAppendingPathComponent:@"Info.plist"];
- if (NSMutableDictionary *info = [NSMutableDictionary dictionaryWithContentsOfFile:plist]) {
- if (NSString *identifier = [info objectForKey:@"CFBundleIdentifier"]) {
- [bundles setObject:path forKey:identifier];
- [removed removeObject:path];
- if (cached != nil) {
- NSMutableDictionary *merged([before objectForKey:identifier]);
- if (merged == nil)
- merged = [NSMutableDictionary dictionary];
- else
- merged = [[merged mutableCopy] autorelease];
- for (NSString *key in cached)
- if (NSObject *value = [info objectForKey:key])
- [merged setObject:value forKey:key];
- else
- [merged removeObjectForKey:key];
- info = merged;
- }
- [info setObject:path forKey:@"Path"];
- [info setObject:@"System" forKey:@"ApplicationType"];
- [after addInfoDictionary:info];
- } else
- fprintf(stderr, "%s missing CFBundleIdentifier", [app UTF8String]);
- }
- }
- } else goto error;
- [cache writeToFile:path atomically:YES];
- if (workspace != nil) {
- if ([workspace respondsToSelector:@selector(invalidateIconCache:)]) {
- for (NSString *identifier in bundles)
- [workspace invalidateIconCache:identifier];
- } else {
- for (NSString *identifier in bundles) {
- NSString *path([bundles objectForKey:identifier]);
- [workspace unregisterApplication:[NSURL fileURLWithPath:path]];
- }
- }
- for (NSString *identifier in bundles) {
- NSString *path([bundles objectForKey:identifier]);
- if (kCFCoreFoundationVersionNumber >= 800)
- [workspace registerApplicationDictionary:[after objectForKey:identifier]];
- else
- [workspace registerApplication:[NSURL fileURLWithPath:path]];
- }
- for (NSString *path in removed)
- [workspace unregisterApplication:[NSURL fileURLWithPath:path]];
- }
- } else fprintf(stderr, "cannot open cache file. incorrect user?\n");
- cached:
- if (respring || kCFCoreFoundationVersionNumber >= 550.32) {
- unlink([[NSString stringWithFormat:@"%@/Library/Caches/com.apple.springboard-imagecache-icons", home] UTF8String]);
- unlink([[NSString stringWithFormat:@"%@/Library/Caches/com.apple.springboard-imagecache-icons.plist", home] UTF8String]);
- unlink([[NSString stringWithFormat:@"%@/Library/Caches/com.apple.springboard-imagecache-smallicons", home] UTF8String]);
- unlink([[NSString stringWithFormat:@"%@/Library/Caches/com.apple.springboard-imagecache-smallicons.plist", home] UTF8String]);
- my_system([[NSString stringWithFormat:@"rm -rf %@/Library/Caches/SpringBoardIconCache", home] UTF8String]);
- my_system([[NSString stringWithFormat:@"rm -rf %@/Library/Caches/SpringBoardIconCache-small", home] UTF8String]);
- my_system([[NSString stringWithFormat:@"rm -rf %@/Library/Caches/com.apple.IconsCache", home] UTF8String]);
- }
- my_system("killall installd");
- } @finally {
- my_system("killall -SIGCONT SpringBoard");
- }
- notify_post("com.apple.mobile.application_installed");
- return 0;
- }
- }
- pid_t pidOfCydia(void) {
- launch_data_t request = launch_data_new_string(LAUNCH_KEY_GETJOBS);
- launch_data_t response = launch_msg(request);
- launch_data_free(request);
- __block pid_t pid=-1;
- if (response == NULL || launch_data_get_type(response) != LAUNCH_DATA_DICTIONARY) return -1;
- xpc_dictionary_apply((xpc_object_t)response, ^bool(const char *key, xpc_object_t value) {
- if (xpc_get_type(value) == XPC_TYPE_DICTIONARY) {
- const char *program = xpc_dictionary_get_string(value, "Program");
- if (program && strcmp(program, "/Applications/Cydia.app/Cydia") == 0) {
- pid = (pid_t)xpc_dictionary_get_int64(value, "PID");
- if (verbose) fprintf(stderr, "Found Cydia running with PID: %d\n", pid);
- return false;
- }
- }
- return true;
- });
- if (pid>0) {
- return pid;
- }
- return -1;
- }
- int optimized_uicache(void) {
- __block int rv=0;
- NSMutableDictionary *registered = [NSMutableDictionary new];
- static void (^readHandler)(NSFileHandle*) = ^(NSFileHandle *fh) {
- NSData *output = [fh readDataToEndOfFile];
- if (output.length==0) return;
- const char *found_path = (const char *)[output bytes];
- NSArray *found = [@(found_path) pathComponents];
- if (found.count >= 3) {
- NSString *appPath = [@"/Applications" stringByAppendingPathComponent:found[2]];
- @synchronized (registered) {
- if (registered[appPath]) return;
- if (verbose) fprintf(stderr, "Updating %s\n", appPath.lastPathComponent.UTF8String);
- registered[appPath] = @YES;
- }
- pid_t cydia_pid;
- if ([found[2] isEqualToString:@"Cydia.app"] &&
- (cydia_pid = pidOfCydia()) > 0) {
- // We are in cydia and trying to refresh it - this will kill it. Let's schedule it for later.
- if (verbose) fprintf(stderr, "Waiting to refresh Cydia...\n");
- pid_t pid = fork();
- if (pid == 0) {
- setpgrp();
- signal(SIGHUP, SIG_IGN);
- signal(SIGPIPE, SIG_IGN);
- fclose(stdin);
- freopen("/dev/null", "a", stderr);
- freopen("/dev/null", "a", stdout);
- pid = fork();
- if (pid == 0) {
- while (kill(cydia_pid, 0)==0) {
- sleep(1);
- }
- const char *uicache = (*_NSGetArgv())[0];
- execl(uicache, uicache, "-vvvvvvv", NULL);
- fprintf(stderr, "Unable to exec\n");
- fflush(stderr);
- exit(-1);
- }
- exit(0);
- } else if (pid > 0) {
- int stat;
- waitpid(pid, &stat, 0);
- return;
- } else {
- fprintf(stderr, "Unable to fork\n");
- }
- }
- if (!registerPath(appPath)) rv++;
- }
- };
- NSFileManager *fm = [NSFileManager defaultManager];
- NSMutableDictionary *apps = [NSMutableDictionary new];
- NSMutableArray *cleanup = [NSMutableArray new];
- NSMutableArray *finds = [NSMutableArray new];
- if (verbose>1) fprintf(stderr, "Enumerating apps\n");
- for (LSApplicationProxy *app in [workspace allApplications]) {
- NSString *path = [[app bundleURL] path];
- if (![path hasPrefix:@"/Applications/"]) continue;
- if (verbose>1) fprintf(stderr, "Checking %s\n", path.lastPathComponent.UTF8String);
-
- NSDate *lastRegistered = [app registeredDate];
-
- if ([fm fileExistsAtPath:path]) {
- // Check for updated components
- NSTask *find = [NSTask new];
- [find setLaunchPath:@"/usr/bin/find"];
- [find setStandardOutput:[NSPipe pipe]];
- NSString *stampPath = [NSString stringWithFormat:@"/var/tmp/uicache.stamp.%@", app.applicationIdentifier];
- [fm createFileAtPath:stampPath contents:nil attributes:@{NSFileModificationDate: lastRegistered}];
- [cleanup addObject:stampPath];
- [find setArguments:@[ path, @"-newer", stampPath, @"-print0", @"-quit"]];
- [finds addObject:find];
- [find launch];
- apps[path.lastPathComponent] = app;
- } else {
- if (verbose) fprintf(stderr, "De-registering removed app: %s\n", path.lastPathComponent.UTF8String);
- @synchronized (registered) {
- if (registered[path]) continue;
- registered[path] = @YES;
- }
- if (!unregisterPath(path)) rv++;
- }
- }
-
- for (NSString* existing in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/Applications" error:nil]) {
- NSString *path = [@"/Applications" stringByAppendingPathComponent:existing];
- if (apps[existing] || registered[path] || ![existing hasSuffix:@".app"]) continue;
- if (verbose) fprintf(stderr, "Registering new app: %s\n", existing.UTF8String);
- @synchronized (registered) {
- registered[path] = @YES;
- }
- if (!registerPath(path)) rv++;
- }
- for (NSTask *find in finds) {
- if (verbose>2) fprintf(stderr, "waiting for find %s\n", [find.arguments componentsJoinedByString:@" "].UTF8String);
- readHandler([find.standardOutput fileHandleForReading]);
- [find waitUntilExit];
- }
- for (NSString *path in cleanup) {
- [fm removeItemAtPath:path error:nil];
- }
- return rv;
- }
- int main(int argc, const char *argv[])
- {
- if (getuid() == 0) {
- // Be mobile
- if (setuid(501)) {
- fprintf(stderr, "Error: unable to become mobile");
- return -1;
- }
- }
- dlopen("/System/Library/PrivateFrameworks/MobileContainerManager.framework/MobileContainerManager", RTLD_LAZY);
- dlopen("/System/Library/PrivateFrameworks/FrontBoardServices.framework/FrontBoardServices", RTLD_LAZY);
- dlopen("/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices", RTLD_LAZY);
- Class $SBSRelaunchAction = objc_getClass("SBSRelaunchAction");
- Class $FBSSystemService = objc_getClass("FBSSystemService");
- $MCMPluginKitPluginDataContainer = objc_getClass("MCMPluginKitPluginDataContainer");
- $MCMAppDataContainer = objc_getClass("MCMAppDataContainer");
- $LSApplicationWorkspace = objc_getClass("LSApplicationWorkspace");
- workspace = [$LSApplicationWorkspace defaultWorkspace];
- static int rv=0;
- @autoreleasepool {
- bool respring=false, do_all=false;
- void (*jb_oneshot_entitle_now)(pid_t a, uint64_t b);
- void *libjb = dlopen("/usr/lib/libjailbreak.dylib", RTLD_LAZY);
-
- if (libjb) {
- dlerror();
- jb_oneshot_entitle_now = (void (*)(pid_t, uint64_t))dlsym(libjb, "jb_oneshot_entitle_now");
- if (!dlerror()) jb_oneshot_entitle_now(getpid(), 2);
- }
-
- NSMutableDictionary *paths = [NSMutableDictionary new];
- NSMutableDictionary *unregister_paths = [NSMutableDictionary new];
- static struct option long_options[] =
- {
- {"all", no_argument, 0, 'a'},
- {"help", no_argument, 0, 'h'},
- {"path", required_argument, 0, 'p'},
- {"unregister", required_argument, 0, 'u'},
- {"respring", no_argument, 0, 'r'},
- {"verbose", no_argument, 0, 'v'},
- {0, 0, 0, 0}
- };
- int option_index = 0;
- char ch;
- bool have_path = false;
- while ((ch = getopt_long(argc, (char *const *)argv, "ap:ru:vh?", long_options, &option_index)) != -1) {
- switch (ch)
- {
- case 'a':
- do_all = true;
- break;
- case 'h':
- usage();
- break;
- case 'p':
- paths[@(optarg)] = @YES;
- have_path = true;
- break;
- case 'r':
- respring = true;
- break;
- case 'u':
- unregister_paths[@(optarg)] = @YES;
- have_path = true;
- break;
- case 'v':
- verbose++;
- break;
- default:
- break;
- }
- }
- if (do_all || !$MCMPluginKitPluginDataContainer || !$MCMAppDataContainer || !$LSApplicationWorkspace) {
- rv = standard_uicache();
- } else if (have_path) {
- for (NSString *path in [paths allKeys]) {
- if (verbose) fprintf(stderr, "Refreshing %s\n", path.UTF8String);
- if (!registerPath(path)) rv++;
- }
- for (NSString *path in [unregister_paths allKeys]) {
- if (!unregisterPath(path)) rv++;
- }
- } else {
- rv += optimized_uicache();
- }
- if ( respring )
- {
- [[[PBSSystemServiceConnection sharedConnection] systemServiceProxy] relaunchBackboardd];
-
- pid_t sb_pid = launch_get_job_pid("com.apple.SpringBoard");
- if ($SBSRelaunchAction && $FBSSystemService) {
- id action = [$SBSRelaunchAction actionWithReason:@"respring" options:RestartRenderServer targetURL:nil];
- id sharedService = [$FBSSystemService sharedService];
- [sharedService sendActions:[NSSet setWithObject:action] withResult:nil];
- for (int i=0; i<100; i++) {
- if (kill(sb_pid, 0)) {
- break;
- }
- usleep(1000);
- }
- } else {
- my_system("launchctl stop com.apple.PineBoard");
- my_system("launchctl stop com.apple.backboardd");
- }
- }
- } // @autoreleasepool
- return rv;
- }
|