From 00a3c32a87c3484a3ec60aa61a9da89f498580c5 Mon Sep 17 00:00:00 2001 From: Mike Pontillo Date: Thu, 8 Nov 2012 21:33:40 -0800 Subject: [PATCH 1/3] Re-target to MacOS 10.7 SDK. (this project was no longer compiling with the latest Xcode) Change-Id: Ia75390332506beebce3fb490fba29e45a0caee24 --- deviceconsole.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deviceconsole.xcodeproj/project.pbxproj b/deviceconsole.xcodeproj/project.pbxproj index baf55ce..cd8ecc3 100644 --- a/deviceconsole.xcodeproj/project.pbxproj +++ b/deviceconsole.xcodeproj/project.pbxproj @@ -146,6 +146,7 @@ INSTALL_PATH = /usr/local/bin; LD_RUNPATH_SEARCH_PATHS = "\"/Applications/Utilities/iPhone Configuration Utility.app/Contents/Frameworks\" \"/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks\""; PRODUCT_NAME = deviceconsole; + SDKROOT = macosx10.7; }; name = Debug; }; @@ -162,6 +163,7 @@ INSTALL_PATH = /usr/local/bin; LD_RUNPATH_SEARCH_PATHS = "\"/Applications/Utilities/iPhone Configuration Utility.app/Contents/Frameworks\" \"/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks\""; PRODUCT_NAME = deviceconsole; + SDKROOT = macosx10.7; }; name = Release; }; From 4ac8f6f413f18666fee7788f7e6d128314949fda Mon Sep 17 00:00:00 2001 From: Mike Pontillo Date: Thu, 8 Nov 2012 21:37:49 -0800 Subject: [PATCH 2/3] Remove hard-coded SDK requirement. This is a better solution than the previous commit, because we won't have to do this again when the 10.7 SDK is obsolete. Change-Id: I34238e317f214804038c15ef28cd52eea3b5d6a8 --- deviceconsole.xcodeproj/project.pbxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deviceconsole.xcodeproj/project.pbxproj b/deviceconsole.xcodeproj/project.pbxproj index cd8ecc3..3515e80 100644 --- a/deviceconsole.xcodeproj/project.pbxproj +++ b/deviceconsole.xcodeproj/project.pbxproj @@ -146,7 +146,6 @@ INSTALL_PATH = /usr/local/bin; LD_RUNPATH_SEARCH_PATHS = "\"/Applications/Utilities/iPhone Configuration Utility.app/Contents/Frameworks\" \"/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks\""; PRODUCT_NAME = deviceconsole; - SDKROOT = macosx10.7; }; name = Debug; }; @@ -163,7 +162,6 @@ INSTALL_PATH = /usr/local/bin; LD_RUNPATH_SEARCH_PATHS = "\"/Applications/Utilities/iPhone Configuration Utility.app/Contents/Frameworks\" \"/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks\""; PRODUCT_NAME = deviceconsole; - SDKROOT = macosx10.7; }; name = Release; }; @@ -177,7 +175,6 @@ GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.5; }; name = Debug; }; @@ -189,7 +186,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = macosx10.5; }; name = Release; }; From cbdf80d130598a8d348c82a65647e2446ee09084 Mon Sep 17 00:00:00 2001 From: Mike Pontillo Date: Thu, 8 Nov 2012 23:43:09 -0800 Subject: [PATCH 3/3] Add timeout functionality. * Now exits the program if either no logs have been seen for the past N seconds (-t ), or if N seconds have elapsed (-t -x). Change-Id: I09eec51dd57ccb44f4e09d339d2664e91795d8fe --- main.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index 7c53dae..52016f9 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,9 @@ static CFMutableDictionaryRef liveConnections; static int debug; static CFStringRef requiredDeviceId; +static int exitAfterTimeout; +static int linesLogged; + static inline void write_fully(int fd, const void *buffer, size_t length) { while (length) { @@ -24,6 +27,26 @@ static inline void write_fully(int fd, const void *buffer, size_t length) } } +static void Timeout() +{ + static int logged = -1; + + if(exitAfterTimeout) { + if(debug) + fprintf(stderr, "[!] Exit due to timeout.\n"); + exit(0); + } + + if(logged != linesLogged) { + logged = linesLogged; + } else { + if(debug) + fprintf(stderr, "[!] Exit after timeout (because nothing else has been logged.)\n"); + + exit(0); + } +} + static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { // Skip null bytes @@ -34,7 +57,7 @@ static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef a buffer++; length--; if (length == 0) - return; + goto exit; } size_t extentLength = 0; while ((buffer[extentLength] != '\0') && extentLength != length) { @@ -44,6 +67,15 @@ static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef a length -= extentLength; buffer += extentLength; } + +exit: + /* + * It turns out that every time we get here, we've logged one complete log + * statement. (which could be more than one line, but you get the idea.) + */ + linesLogged++; + + return; } static void DeviceNotificationCallback(am_device_notification_callback_info *info, void *unknown) @@ -70,7 +102,11 @@ static void DeviceNotificationCallback(am_device_notification_callback_info *inf if (AMDeviceStartSession(device) == MDERR_OK) { service_conn_t connection; if (AMDeviceStartService(device, AMSVC_SYSLOG_RELAY, &connection, NULL) == MDERR_OK) { - CFSocketRef socket = CFSocketCreateWithNative(kCFAllocatorDefault, connection, kCFSocketDataCallBack, SocketCallback, NULL); + CFSocketRef socket = CFSocketCreateWithNative(kCFAllocatorDefault, + connection, + kCFSocketDataCallBack, + SocketCallback, + NULL); if (socket) { CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0); if (source) { @@ -121,12 +157,25 @@ static void DeviceNotificationCallback(am_device_notification_callback_info *inf int main (int argc, char * const argv[]) { + double timeout = 0; + if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) { - fprintf(stderr, "Usage: %s [options]\nOptions:\n -d Include connect/disconnect messages in standard out\n -u Show only logs from a specific device\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); + fprintf(stderr, + "Usage: %s [options]\nOptions:\n" + " -d Include connect/disconnect messages in standard out,\n" + " and exit reason in standard err.\n" + " -u Show only logs from a specific device.\n" + " -t Exit after the specified timeout, in seconds (can be decimal),\n" + " if there have been no more logs in that timeframe.\n" + " -x (Must use with -t.) Exit unconditionally after the timeout,\n" + " even if more logs are coming in.\n" + "\nControl-C to disconnect\n" + "Mail bug reports and suggestions to \n", + argv[0]); return 1; } int c; - while ((c = getopt(argc, argv, "du:")) != -1) + while ((c = getopt(argc, argv, "dxt:u:")) != -1) switch (c) { case 'd': @@ -137,8 +186,14 @@ int main (int argc, char * const argv[]) CFRelease(requiredDeviceId); requiredDeviceId = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingASCII); break; + case 't': + timeout = atof(optarg); + break; + case 'x': + exitAfterTimeout = 1; + break; case '?': - if (optopt == 'u') + if (optopt == 'u' || optopt == 't') fprintf(stderr, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c'.\n", optopt); @@ -151,6 +206,21 @@ int main (int argc, char * const argv[]) liveConnections = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); am_device_notification *notification; AMDeviceNotificationSubscribe(DeviceNotificationCallback, 0, 0, NULL, ¬ification); + + if(timeout != 0) { + CFRunLoopTimerRef timer = CFRunLoopTimerCreate(NULL, + /* give it a couple extra seconds to connect */ + CFAbsoluteTimeGetCurrent() + 2.0 + timeout, + timeout, + 0, /* flags */ + 0, /* order */ + (CFRunLoopTimerCallBack) Timeout, + NULL); + + CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes); + } + + CFRunLoopRun(); return 0; }