From bb1c419ccbc0db9f1f4cec0c7d0602871be33018 Mon Sep 17 00:00:00 2001
From: "Jay Freeman (saurik)" <saurik@saurik.com>
Date: Sat, 31 Oct 2009 21:48:05 +0000
Subject: [PATCH] Added runloop detection support, ported Handler back to the
 iPhone, setup RunLoop bridging, and added an asser to check for working
 nlist() support.

---
 Bridge.def      | 91 ++++++++++++++++++++++++++++++++++++++++++++-----
 Handler.mm      | 22 +++++++++++-
 Library.cpp     |  5 ---
 Mach/Inject.cpp |  1 +
 4 files changed, 105 insertions(+), 14 deletions(-)

diff --git a/Bridge.def b/Bridge.def
index 7ce9cda..26797e3 100644
--- a/Bridge.def
+++ b/Bridge.def
@@ -19,6 +19,9 @@ T boolean B
 T float f
 T double d
 
+T Boolean B
+T SInt32 {int}
+
 S CGPoint "x"f"y"f
 S CGRect "origin"{CGPoint}"size"{CGSize}
 S CGSize "width"f"height"f
@@ -756,6 +759,24 @@ f CoreFoundation
 
 F CFRangeMake {CFRange}{CFIndex}{CFIndex}
 
+# Time Utilities
+
+T CFAbsoluteTime {CFTimeInterval}
+S CFGregorianDate "year"{SInt32}"month"{SInt8}"day"{SInt8}"hour"{SInt8}"minute"{SInt8}"second"{double}
+S CFGregorianUnits "years"{SInt32}"months"{SInt32}"days"{SInt32}"hours"{SInt32}"minutes"{SInt32}"second"{double}
+T CFTimeInterval {double}
+
+C kCFGregorianUnitsYears 1<<0
+C kCFGregorianUnitsMonths 1<<1
+C kCFGregorianUnitsDays 1<<2
+C kCFGregorianUnitsHours 1<<3
+C kCFGregorianUnitsMinutes 1<<4
+C kCFGregorianUnitsSeconds 1<<5
+C kCFGregorianAllUnits 0x00FFFFFF
+
+V kCFAbsoluteTimeIntervalSince1970 {CFTimeInterval}
+V kCFAbsoluteTimeIntervalSince1904 {CFTimeInterval}
+
 # CFComparatorFunction
 
 T CFIndex l
@@ -857,6 +878,68 @@ V kCFAllocatorMallocZone {CFAllocatorRef}
 V kCFAllocatorNull {CFAllocatorRef}
 V kCFAllocatorUseContext {CFAllocatorRef}
 
+# CFByteOrderUtils
+
+E __CFByteOrder
+C CFByteOrderUnknown 0
+C CFByteOrderLittleEndian 1
+C CFByteOrderBigEndian 2
+T CFByteOrder __CFByteOrder
+
+# CFArray
+
+T CFArrayRef @
+
+# CFRunLoop
+
+F CFRunLoopGetCurrent {CFRunLoopRef}
+F CFRunLoopGetMain {CFRunLoopRef}
+
+F CFRunLoopRun v
+F CFRunLoopRunInMode {SInt32}{CFStringRef}{CFTimeInterval}{Boolean}
+F CFRunLoopWakeUp v{CFRunLoopRef}
+F CFRunLoopStop v{CFRunLoopRef}
+F CFRunLoopIsWaiting {Boolean}{CFRunLoopRef}
+
+F CFRunLoopAddSource v{CFRunLoopRef}{CFRunLoopSourceRef}{CFStringRef}
+F CFRunLoopContainsSource {Boolean}{CFRunLoopRef}{CFRunLoopSourceRef}{CFStringRef}
+F CFRunLoopRemoveSource v{CFRunLoopRef}{CFRunLoopSourceRef}{CFStringRef}
+
+F CFRunLoopAddObserver v{CFRunLoopRef}{CFRunLoopObserverRef}{CFStringRef}
+F CFRunLoopContainsObserver {Boolean}{CFRunLoopRef}{CFRunLoopObserverRef}{CFStringRef}
+F CFRunLoopRemoveObserver v{CFRunLoopRef}{CFRunLoopObserverRef}{CFStringRef}
+
+F CFRunLoopAddCommonMode v{CFRunLoopRef}{CFStringRef}
+F CFRunLoopCopyAllModes {CFArrayRef}{CFRunLoopRef}
+F CFRunLoopCopyCurrentMode {CFStringRef}{CFRunLoopRef}
+
+F CFRunLoopAddTimer v{CFRunLoopRef}{CFRunLoopTimerRef}{CFStringRef}
+F CFRunLoopGetNextTimerFireDate {CFAbsoluteTime}{CFRunLoopRef}{CFStringRef}
+F CFRunLoopRemoveTimer v{CFRunLoopRef}{CFRunLoopTimerRef}{CFStringRef}
+F CFRunLoopContainsTimer {Boolean}{CFRunLoopRef}{CFRunLoopTimerRef}{CFStringRef}
+
+# F CFRunLoopPerformBlock
+
+F CFRunLoopGetTypeID {CFTypeID}
+
+T CFRunLoopRef @
+
+C kCFRunLoopRunFinished 1
+C kCFRunLoopRunStopped 2
+C kCFRunLoopRunTimedOut 3
+C kCFRunLoopRunHandledSource 4
+
+V kCFRunLoopCommonModes {CFStringRef}
+V kCFRunLoopDefaultMode {CFStringRef}
+
+# CFRunLoopTimer
+
+T CFRunLoopTimerRef @
+
+# CFString
+
+T CFStringRef @
+
 # CFType
 
 F CFGetAllocator {CFAllocatorRef}{CFTypeRef}
@@ -885,14 +968,6 @@ f CoreGraphics
 
 T CGFloat f
 
-# CFByteOrderUtils
-
-E __CFByteOrder
-C CFByteOrderUnknown 0
-C CFByteOrderLittleEndian 1
-C CFByteOrderBigEndian 2
-T CFByteOrder __CFByteOrder
-
 # CGAffineTransform
 
 F CGAffineTransformMake {CGAffineTransform}{CGFloat}{CGFloat}{CGFloat}{CGFloat}{CGFloat}{CGFloat}
diff --git a/Handler.mm b/Handler.mm
index 2a42ef0..79528c4 100644
--- a/Handler.mm
+++ b/Handler.mm
@@ -49,6 +49,11 @@
 #include <unistd.h>
 #include <sstream>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
 struct CYExecute_ {
     apr_pool_t *pool_;
     const char * volatile data_;
@@ -93,6 +98,13 @@ struct CYClient :
 
         CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
 
+        bool dispatch;
+        if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
+            dispatch = true;
+            CFRelease(mode);
+        } else
+            dispatch = false;
+
         for (;;) {
             size_t size;
             if (!CYRecvAll(socket_, &size, sizeof(size)))
@@ -115,6 +127,8 @@ struct CYClient :
                 json = NULL;
                 size = _not(size_t);
             } else {
+                NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
+
                 CYContext context(driver.pool_);
                 driver.program_->Replace(context);
                 std::ostringstream str;
@@ -122,9 +136,15 @@ struct CYClient :
                 out << *driver.program_;
                 std::string code(str.str());
                 CYExecute_ execute = {pool, code.c_str()};
-                [client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
+                NSValue *value([NSValue valueWithPointer:&execute]);
+                if (dispatch)
+                    [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
+                else
+                    [client execute:value];
                 json = execute.data_;
                 size = json == NULL ? _not(size_t) : strlen(json);
+
+                [ar release];
             }
 
             if (!CYSendAll(socket_, &size, sizeof(size)))
diff --git a/Library.cpp b/Library.cpp
index 34763fb..a981b2b 100644
--- a/Library.cpp
+++ b/Library.cpp
@@ -61,11 +61,6 @@
 #include <sstream>
 #include <cmath>
 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-
 #include "Parser.hpp"
 #include "Cycript.tab.hh"
 
diff --git a/Mach/Inject.cpp b/Mach/Inject.cpp
index a2c5f04..6eb9dad 100644
--- a/Mach/Inject.cpp
+++ b/Mach/Inject.cpp
@@ -42,6 +42,7 @@ void InjectLibrary(pid_t pid) {
     nl[0].n_un.n_name = (char *) "__pthread_set_self";
     nlist("/usr/lib/libSystem.B.dylib", nl);
     nlset(baton->_pthread_set_self, nl, 0);
+    _assert(baton->_pthread_set_self != NULL);
 
     baton->pthread_create = &pthread_create;
     baton->pthread_join = &pthread_join;
-- 
2.50.0

