/* Cydia Substrate - Powerful Code Insertion Platform
* Copyright (C) 2008-2010 Jay Freeman (saurik)
*/
/* GNU Lesser General Public License, Version 3 {{{ */
/*
* Substrate is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Substrate 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Substrate. If not, see .
**/
/* }}} */
#include
#import
#include
#include
void SavePropertyList(CFPropertyListRef plist, char *path, CFURLRef url, CFPropertyListFormat format) {
if (path[0] != '\0')
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (uint8_t *) path, strlen(path), false);
CFWriteStreamRef stream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, url);
CFWriteStreamOpen(stream);
CFPropertyListWriteToStream(plist, stream, format, NULL);
CFWriteStreamClose(stream);
}
#define dylib_ @"/Library/MobileSubstrate/MobileSubstrate.dylib"
bool HookEnvironment(const char *path) {
CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (uint8_t *) path, strlen(path), false);
CFPropertyListRef plist; {
CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
CFReadStreamOpen(stream);
plist = CFPropertyListCreateFromStream(kCFAllocatorDefault, stream, 0, kCFPropertyListMutableContainers, NULL, NULL);
CFReadStreamClose(stream);
}
NSMutableDictionary *root = (NSMutableDictionary *) plist;
if (root == nil)
return false;
NSMutableDictionary *ev = [root objectForKey:@"EnvironmentVariables"];
if (ev == nil)
return false;
NSString *il = [ev objectForKey:@"DYLD_INSERT_LIBRARIES"];
if (il == nil)
return false;
NSArray *cm = [il componentsSeparatedByString:@":"];
unsigned index = [cm indexOfObject:dylib_];
if (index == INT_MAX)
return false;
NSMutableArray *cmm = [NSMutableArray arrayWithCapacity:16];
[cmm addObjectsFromArray:cm];
[cmm removeObject:dylib_];
if ([cmm count] != 0)
[ev setObject:[cmm componentsJoinedByString:@":"] forKey:@"DYLD_INSERT_LIBRARIES"];
else if ([ev count] == 1)
[root removeObjectForKey:@"EnvironmentVariables"];
else
[ev removeObjectForKey:@"DYLD_INSERT_LIBRARIES"];
SavePropertyList(plist, "", url, kCFPropertyListBinaryFormat_v1_0);
return true;
}
#define HookEnvironment(name) \
HookEnvironment("/System/Library/LaunchDaemons/" name ".plist")
int main(int argc, char *argv[]) {
if (argc < 2 || (
strcmp(argv[1], "abort-install") != 0 &&
strcmp(argv[1], "remove") != 0
)) return 0;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// XXX: do not use for now due to later reboot
#define HookEnvironment_(plist) \
if (HookEnvironment(plist)) \
system("launchctl unload "plist"; launchctl load "plist"");
HookEnvironment("com.apple.mediaserverd");
HookEnvironment("com.apple.itunesstored");
HookEnvironment("com.apple.CommCenter");
HookEnvironment("com.apple.AOSNotification");
HookEnvironment("com.apple.BTServer");
HookEnvironment("com.apple.iapd");
HookEnvironment("com.apple.lsd");
HookEnvironment("com.apple.imagent");
HookEnvironment("com.apple.mobile.lockdown");
HookEnvironment("com.apple.itdbprep.server");
HookEnvironment("com.apple.locationd");
HookEnvironment("com.apple.mediaremoted");
HookEnvironment("com.apple.frontrow");
const char *finish = "restart";
if (HookEnvironment("com.apple.SpringBoard"))
finish = "reload";
// XXX: damn you khan!
finish = "reboot";
const char *cydia = getenv("CYDIA");
if (cydia != NULL) {
int fd = [[[[NSString stringWithUTF8String:cydia] componentsSeparatedByString:@" "] objectAtIndex:0] intValue];
FILE *fout = fdopen(fd, "w");
fprintf(fout, "finish:%s\n", finish);
fclose(fout);
}
[pool release];
return 0;
}