Code:
/*
* Gestures tweak
* Replacement for jailbreak executable in redsn0w ramdisk
*
* - dB
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
static int execute ( int *status, const char *command, char *arguments[] ) {
// Fork the process
int result = fork ();
if ( result == -1 ) {
perror ( "fork" ); return -1;
}
// Child process
else if ( result == 0 ) {
execv ( command, arguments );
perror ( "execv" );
exit(-1);
}
// Parent process
else {
// Wait for the child process to end
if ( waitpid ( result, status, 0 ) == -1 ) {
perror ( "waitpid" ); return -1;
} return 0;
}
}
static int executev ( int *status, const char *command, ... ) {
// Argument list
int argc = 0;
char* argv[512];
// Setup variable arguments
va_list vargs;
va_start ( vargs, command );
// Add passed arguments to the list
while ( argc++ < (sizeof(argv)/sizeof(argv[0])) ) {
int i = argc - 1;
argv[i] = va_arg ( vargs, char* );
if ( !argv[i] ) break;
} argv[argc] = NULL;
// Execute the command
int result = execute ( status, command, argv );
// Cleanup and return the result
va_end ( vargs );
return result;
}
static int modifycapability ( const char *capability, const char *device, int enable ) {
// Setup the path
char path[PATH_MAX];
snprintf ( path, sizeof ( path ), "/System/Library/CoreServices/SpringBoard.app/%s.plist", device );
// Perform the operation and return the result
int status = 0;
int result = executev ( &status, "/plutil", "/plutil",
"-key", "capabilities",
"-key", capability,
enable ? "-true" : "-false",
path, NULL
); return ( result != 0 || !(WIFEXITED(status) && WEXITSTATUS(status) == 0) ) ? -1 : 0;
}
static int copy ( const char *sourcepath, const char *targetpath ) {
// The reading buffer
char buffer[512];
// Open the source and target files
FILE* source = fopen ( sourcepath, "rb" );
if ( !source ) { perror ( "fopen" ); return -1; }
FILE* target = fopen ( targetpath, "wb" );
if ( !target ) { fclose ( source ); perror ( "fopen" ); return -1; }
// Perform the copy
for ( ;; ) {
int count = fread ( buffer, 1, sizeof ( buffer ), source );
if ( count <= 0 ) break;
fwrite ( buffer, 1, count, target );
}
// Cleanup
fclose ( source );
fclose ( target );
return 0;
}
static int replace ( const char *path, const char *pattern, const char *replacement ) {
// Open the source and target files
FILE* source = fopen ( path, "rb" );
if ( !source ) { perror ( "fopen" ); return -1; }
FILE* target = fopen ( "/tmp/replacement", "wb" );
if ( !target ) { fclose ( source ); perror ( "fopen" ); return -1; }
// Initial allocations and length calculations
int repllen = strlen ( replacement );
int pattlen = strlen ( pattern );
int bufflen = pattlen * 5;
char* buffer = malloc ( bufflen + 1 );
// Perform the search and replace
for ( ;; ) {
int count = fread ( buffer, 1, bufflen, source );
if ( count < pattlen ) {
fwrite ( buffer, 1, count, target ); break;
}
int i; for ( i = 0; i <= count - pattlen; i++ ) {
// If a match is found
if ( memcmp ( buffer + i, pattern, pattlen ) == 0 ) {
fwrite ( replacement, 1, repllen, target );
i += pattlen - 1;
}
// No match was found
else {
fwrite ( buffer + i, 1, 1, target );
}
} fwrite ( buffer + i, 1, count - i, target );
}
// Cleanup
fclose ( source );
fclose ( target );
free ( buffer );
// Copy
copy ( "/tmp/replacement", path );
unlink ( "/tmp/replacement" );
return 0;
}
int main () {
// Op status
int status = 0;
// Greeting message
printf ( "\n" ); // Initial blank line
printf ( "Gestures & display mirroring for iPad 1 (w/o Jailbreak)\n"
"by dB\n\n" ); fflush ( stdout );
// Attempt to update SpringBoard capabilities
printf ( "Updating SpringBoard capabilities...\n" );
printf ( "Enabling multitasking-gestures...\n" );
printf ( "%s\n",
modifycapability ( "multitasking-gestures", "K48AP", 1 ) == 0 ? "OK" : "FAIL" );
printf ( "Enabling display-mirroring...\n" );
printf ( "%s\n",
modifycapability ( "display-mirroring", "K48AP", 1 ) == 0 ? "OK" : "FAIL" );
// Convert /Applications/Preferences.app/General.plist into XML format
printf ( "Converting Preferences/General.plist into XML...\n" );
status = executev ( NULL, "/plutil", "/plutil",
"-xml", "/Applications/Preferences.app/General.plist", NULL
); printf ( "%s\n", (status == 0) ? "OK" : "FAIL" );
// Patch the file, correcting the misspelled "Mutltitasking_Gesture" to "Multitasking_Gesture"
printf ( "Patching Preferences/General.plist...\n" );
status = replace ( "/Applications/Preferences.app/General.plist", "Mutltitasking_Gesture", "Multitasking_Gesture" );
printf ( "%s\n", (status == 0) ? "OK" : "FAIL" );
// Convert /Applications/Preferences.app/General.plist back into binary format
printf ( "Converting Preferences/General.plist back into binary...\n" );
status = executev ( NULL, "/plutil", "/plutil",
"-binary", "/Applications/Preferences.app/General.plist", NULL
); printf ( "%s\n", (status == 0) ? "OK" : "FAIL" );
// Perform a disk sync
printf ( "\n" );
printf ( "Performing a sync... " ); fflush ( stdout );
sync (); printf ( "OK\n" );
// Countdown to reboot
printf ( "\n" );
printf ( "Rebooting in... " );
int i; for ( i = 10; i >= 1; i-- ) {
printf ( "%d ", i ); fflush ( stdout );
sleep ( 2 );
} printf ( "0!\n" );
// Reboot the device
reboot ( 0 );
return EXIT_SUCCESS;
}
And here is the full redsn0w application with the modifications: