From 2642c17eb595bebcb74f470b877ab6857209f12a Mon Sep 17 00:00:00 2001 From: Dany Lisiansky Date: Fri, 31 Jul 2015 16:35:34 +0300 Subject: [PATCH 01/13] Support for regular expression message filtering (that dosn't crop multiline messages like grep) --- main.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index f294ca3..22a8b6d 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "MobileDevice.h" @@ -13,6 +14,7 @@ static CFMutableDictionaryRef liveConnections; static int debug; static CFStringRef requiredDeviceId; static char *requiredProcessName; +static regex_t *requiredRegex; static void (*printMessage)(int fd, const char *, size_t); static void (*printSeparator)(int fd); @@ -49,6 +51,8 @@ static unsigned char should_print_message(const char *buffer, size_t length) { if (length < 3) return 0; // don't want blank lines + unsigned char should_print = 1; + size_t space_offsets[3]; find_space_offsets(buffer, length, space_offsets); @@ -64,16 +68,24 @@ static unsigned char should_print_message(const char *buffer, size_t length) if (processName[i] == '[') processName[i] = '\0'; - if (strcmp(processName, requiredProcessName) != 0){ - free(processName); - return 0; - } + if (strcmp(processName, requiredProcessName) != 0) + should_print = 0; + free(processName); } + if (requiredRegex != NULL) { + char *message = malloc(length + 1); + memcpy(message, buffer, length + 1); + message[length + 1] = '\0'; + + if (regexec(requiredRegex, message, 0, NULL, 0) == REG_NOMATCH) + should_print = 0; + } + // More filtering options can be added here and return 0 when they won't meed filter criteria - return 1; + return should_print; } #define write_const(fd, text) write_fully(fd, text, sizeof(text)-1) @@ -282,14 +294,14 @@ static void color_separator(int fd) int main (int argc, char * const argv[]) { if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) { - fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\tInclude connect/disconnect messages in standard out\n -u \t\tShow only logs from a specific device\n -p \tShow only logs from a specific process\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); + fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\tInclude connect/disconnect messages in standard out\n -u \t\tShow only logs from a specific device\n -p \tShow only logs from a specific process\n -r \tFilter messages by regular expression.\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); return 1; } int c; bool use_separators = false; bool force_color = false; - while ((c = getopt(argc, argv, "dcsu:p:")) != -1) + while ((c = getopt(argc, argv, "dcsu:p:r:")) != -1) switch (c) { case 'd': @@ -312,6 +324,13 @@ int main (int argc, char * const argv[]) strcpy(requiredProcessName, optarg); break; + case 'r': + requiredRegex = malloc(sizeof(regex_t)); + if (regcomp(requiredRegex, optarg, REG_EXTENDED | REG_NEWLINE | REG_ICASE)) { + fprintf(stderr, "Error: Could not compile regex %s.\n", optarg); + return 1; + } + break; case '?': if (optopt == 'u') fprintf(stderr, "Option -%c requires an argument.\n", optopt); From 8dd1858f0138fd038ca4cb4a9d383c2bb740c501 Mon Sep 17 00:00:00 2001 From: DanyL Date: Fri, 31 Jul 2015 17:10:03 +0300 Subject: [PATCH 02/13] Added support for XcodeColors, and a hidden -x option to force XcodeColors. --- main.c | 76 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/main.c b/main.c index 22a8b6d..9709b99 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,24 @@ static regex_t *requiredRegex; static void (*printMessage)(int fd, const char *, size_t); static void (*printSeparator)(int fd); +static char *COLOR_RESET = NULL; +static char *COLOR_NORMAL = NULL; +static char *COLOR_DARK = NULL; +static char *COLOR_RED = NULL; +static char *COLOR_DARK_RED = NULL; +static char *COLOR_GREEN = NULL; +static char *COLOR_DARK_GREEN = NULL; +static char *COLOR_YELLOW = NULL; +static char *COLOR_DARK_YELLOW = NULL; +static char *COLOR_BLUE = NULL; +static char *COLOR_DARK_BLUE = NULL; +static char *COLOR_MAGENTA = NULL; +static char *COLOR_DARK_MAGENTA = NULL; +static char *COLOR_CYAN = NULL; +static char *COLOR_DARK_CYAN = NULL; +static char *COLOR_WHITE = NULL; +static char *COLOR_DARK_WHITE = NULL; + static inline void write_fully(int fd, const char *buffer, size_t length) { while (length) { @@ -88,25 +106,29 @@ static unsigned char should_print_message(const char *buffer, size_t length) return should_print; } -#define write_const(fd, text) write_fully(fd, text, sizeof(text)-1) +#define write_const(fd, text) write_fully(fd, text, strlen(text)) +#define stringify(x) #x +#define xcode_color_with_rgb(type, r, g, b) "\e[" type stringify(r) "," stringify(g) "," stringify(b) ";" -#define COLOR_RESET "\e[m" -#define COLOR_NORMAL "\e[0m" -#define COLOR_DARK "\e[2m" -#define COLOR_RED "\e[0;31m" -#define COLOR_DARK_RED "\e[2;31m" -#define COLOR_GREEN "\e[0;32m" -#define COLOR_DARK_GREEN "\e[2;32m" -#define COLOR_YELLOW "\e[0;33m" -#define COLOR_DARK_YELLOW "\e[2;33m" -#define COLOR_BLUE "\e[0;34m" -#define COLOR_DARK_BLUE "\e[2;34m" -#define COLOR_MAGENTA "\e[0;35m" -#define COLOR_DARK_MAGENTA "\e[2;35m" -#define COLOR_CYAN "\e[0;36m" -#define COLOR_DARK_CYAN "\e[2;36m" -#define COLOR_WHITE "\e[0;37m" -#define COLOR_DARK_WHITE "\e[0;37m" +static void set_colors(xcode_colors) { + COLOR_RESET = (xcode_colors) ? "\e[;" : "\e[m"; + COLOR_NORMAL = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 0) : "\e[0m"; + COLOR_DARK = (xcode_colors) ? xcode_color_with_rgb("fg", 207, 201, 189) : "\e[2m"; + COLOR_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 31, 2) : "\e[0;31m"; + COLOR_DARK_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 148, 18, 1) : "\e[2;31m"; + COLOR_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 2, 255, 14) : "\e[0;32m"; + COLOR_DARK_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 1, 139, 8) : "\e[2;32m"; + COLOR_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 228, 0) : "\e[0;33m"; + COLOR_DARK_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 167, 149, 1) : "\e[2;33m"; + COLOR_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 255) : "\e[0;34m"; + COLOR_DARK_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 100) : "\e[2;34m"; + COLOR_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 213, 149, 139) : "\e[0;35m"; + COLOR_DARK_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 145, 100, 165) : "\e[2;35m"; + COLOR_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 45, 253, 255) : "\e[0;36m"; + COLOR_DARK_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 34, 129, 128) : "\e[2;36m"; + COLOR_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 255, 255) : "\e[0;37m"; + COLOR_DARK_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 180, 180, 180) : "\e[0;37m"; +} static void write_colored(int fd, const char *buffer, size_t length) { @@ -288,7 +310,12 @@ static void plain_separator(int fd) static void color_separator(int fd) { - write_const(fd, COLOR_DARK_WHITE "--" COLOR_RESET "\n"); + size_t buffer_lentgh = sizeof(char) * (strlen(COLOR_DARK_WHITE) + strlen(COLOR_RESET) + 3); + char *buffer = malloc(buffer_lentgh); + sprintf(buffer, "%s--%s\n", COLOR_DARK_WHITE, COLOR_RESET); + + write_const(fd, buffer); + free(buffer); } int main (int argc, char * const argv[]) @@ -299,9 +326,10 @@ int main (int argc, char * const argv[]) } int c; bool use_separators = false; - bool force_color = false; + bool force_color = isatty(1); + bool xcode_colors = (getenv("XcodeColors")); - while ((c = getopt(argc, argv, "dcsu:p:r:")) != -1) + while ((c = getopt(argc, argv, "dcxsu:p:r:")) != -1) switch (c) { case 'd': @@ -310,6 +338,9 @@ int main (int argc, char * const argv[]) case 'c': force_color = true; break; + case 'x': + xcode_colors = true; + break; case 's': use_separators = true; break; @@ -342,7 +373,8 @@ int main (int argc, char * const argv[]) default: abort(); } - if (force_color || isatty(1)) { + if (force_color || xcode_colors) { + set_colors(xcode_colors); printMessage = &write_colored; printSeparator = use_separators ? &color_separator : &no_separator; } else { From ebd7f4878ca49686b6e899d12abbcbd2da1a65db Mon Sep 17 00:00:00 2001 From: DanyL Date: Fri, 31 Jul 2015 20:41:37 +0300 Subject: [PATCH 03/13] Added support for XcodeColors, and a hidden -x option to force XcodeColors. --- main.c | 76 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/main.c b/main.c index 22a8b6d..9709b99 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,24 @@ static regex_t *requiredRegex; static void (*printMessage)(int fd, const char *, size_t); static void (*printSeparator)(int fd); +static char *COLOR_RESET = NULL; +static char *COLOR_NORMAL = NULL; +static char *COLOR_DARK = NULL; +static char *COLOR_RED = NULL; +static char *COLOR_DARK_RED = NULL; +static char *COLOR_GREEN = NULL; +static char *COLOR_DARK_GREEN = NULL; +static char *COLOR_YELLOW = NULL; +static char *COLOR_DARK_YELLOW = NULL; +static char *COLOR_BLUE = NULL; +static char *COLOR_DARK_BLUE = NULL; +static char *COLOR_MAGENTA = NULL; +static char *COLOR_DARK_MAGENTA = NULL; +static char *COLOR_CYAN = NULL; +static char *COLOR_DARK_CYAN = NULL; +static char *COLOR_WHITE = NULL; +static char *COLOR_DARK_WHITE = NULL; + static inline void write_fully(int fd, const char *buffer, size_t length) { while (length) { @@ -88,25 +106,29 @@ static unsigned char should_print_message(const char *buffer, size_t length) return should_print; } -#define write_const(fd, text) write_fully(fd, text, sizeof(text)-1) +#define write_const(fd, text) write_fully(fd, text, strlen(text)) +#define stringify(x) #x +#define xcode_color_with_rgb(type, r, g, b) "\e[" type stringify(r) "," stringify(g) "," stringify(b) ";" -#define COLOR_RESET "\e[m" -#define COLOR_NORMAL "\e[0m" -#define COLOR_DARK "\e[2m" -#define COLOR_RED "\e[0;31m" -#define COLOR_DARK_RED "\e[2;31m" -#define COLOR_GREEN "\e[0;32m" -#define COLOR_DARK_GREEN "\e[2;32m" -#define COLOR_YELLOW "\e[0;33m" -#define COLOR_DARK_YELLOW "\e[2;33m" -#define COLOR_BLUE "\e[0;34m" -#define COLOR_DARK_BLUE "\e[2;34m" -#define COLOR_MAGENTA "\e[0;35m" -#define COLOR_DARK_MAGENTA "\e[2;35m" -#define COLOR_CYAN "\e[0;36m" -#define COLOR_DARK_CYAN "\e[2;36m" -#define COLOR_WHITE "\e[0;37m" -#define COLOR_DARK_WHITE "\e[0;37m" +static void set_colors(xcode_colors) { + COLOR_RESET = (xcode_colors) ? "\e[;" : "\e[m"; + COLOR_NORMAL = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 0) : "\e[0m"; + COLOR_DARK = (xcode_colors) ? xcode_color_with_rgb("fg", 207, 201, 189) : "\e[2m"; + COLOR_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 31, 2) : "\e[0;31m"; + COLOR_DARK_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 148, 18, 1) : "\e[2;31m"; + COLOR_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 2, 255, 14) : "\e[0;32m"; + COLOR_DARK_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 1, 139, 8) : "\e[2;32m"; + COLOR_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 228, 0) : "\e[0;33m"; + COLOR_DARK_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 167, 149, 1) : "\e[2;33m"; + COLOR_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 255) : "\e[0;34m"; + COLOR_DARK_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 100) : "\e[2;34m"; + COLOR_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 213, 149, 139) : "\e[0;35m"; + COLOR_DARK_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 145, 100, 165) : "\e[2;35m"; + COLOR_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 45, 253, 255) : "\e[0;36m"; + COLOR_DARK_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 34, 129, 128) : "\e[2;36m"; + COLOR_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 255, 255) : "\e[0;37m"; + COLOR_DARK_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 180, 180, 180) : "\e[0;37m"; +} static void write_colored(int fd, const char *buffer, size_t length) { @@ -288,7 +310,12 @@ static void plain_separator(int fd) static void color_separator(int fd) { - write_const(fd, COLOR_DARK_WHITE "--" COLOR_RESET "\n"); + size_t buffer_lentgh = sizeof(char) * (strlen(COLOR_DARK_WHITE) + strlen(COLOR_RESET) + 3); + char *buffer = malloc(buffer_lentgh); + sprintf(buffer, "%s--%s\n", COLOR_DARK_WHITE, COLOR_RESET); + + write_const(fd, buffer); + free(buffer); } int main (int argc, char * const argv[]) @@ -299,9 +326,10 @@ int main (int argc, char * const argv[]) } int c; bool use_separators = false; - bool force_color = false; + bool force_color = isatty(1); + bool xcode_colors = (getenv("XcodeColors")); - while ((c = getopt(argc, argv, "dcsu:p:r:")) != -1) + while ((c = getopt(argc, argv, "dcxsu:p:r:")) != -1) switch (c) { case 'd': @@ -310,6 +338,9 @@ int main (int argc, char * const argv[]) case 'c': force_color = true; break; + case 'x': + xcode_colors = true; + break; case 's': use_separators = true; break; @@ -342,7 +373,8 @@ int main (int argc, char * const argv[]) default: abort(); } - if (force_color || isatty(1)) { + if (force_color || xcode_colors) { + set_colors(xcode_colors); printMessage = &write_colored; printSeparator = use_separators ? &color_separator : &no_separator; } else { From 21eabefda00fee073d4a7493f08b85d5d4c10caf Mon Sep 17 00:00:00 2001 From: DanyL Date: Fri, 31 Jul 2015 20:40:46 +0300 Subject: [PATCH 04/13] -x now toggles Xcode mode, which disable colors, unless is set to "YES" --- main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 9709b99..ad7e20d 100644 --- a/main.c +++ b/main.c @@ -327,7 +327,8 @@ int main (int argc, char * const argv[]) int c; bool use_separators = false; bool force_color = isatty(1); - bool xcode_colors = (getenv("XcodeColors")); + bool xcode_colors = ((getenv("XcodeColors")) ? strstr(getenv("XcodeColors"), "YES") != NULL : false); + bool in_xcode = xcode_colors; while ((c = getopt(argc, argv, "dcxsu:p:r:")) != -1) switch (c) @@ -339,7 +340,7 @@ int main (int argc, char * const argv[]) force_color = true; break; case 'x': - xcode_colors = true; + in_xcode = true; break; case 's': use_separators = true; @@ -373,7 +374,8 @@ int main (int argc, char * const argv[]) default: abort(); } - if (force_color || xcode_colors) { + + if ((!in_xcode && force_color) || xcode_colors) { set_colors(xcode_colors); printMessage = &write_colored; printSeparator = use_separators ? &color_separator : &no_separator; From b6eaa9c620071028a9e6702704b9ac4a3a32a1b5 Mon Sep 17 00:00:00 2001 From: DanyL Date: Fri, 31 Jul 2015 20:38:26 +0300 Subject: [PATCH 05/13] Added help description for -x option --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index ad7e20d..38de510 100644 --- a/main.c +++ b/main.c @@ -321,7 +321,7 @@ static void color_separator(int fd) int main (int argc, char * const argv[]) { if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) { - fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\tInclude connect/disconnect messages in standard out\n -u \t\tShow only logs from a specific device\n -p \tShow only logs from a specific process\n -r \tFilter messages by regular expression.\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); + fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\t\tInclude connect/disconnect messages in standard out\n -u \t\t\tShow only logs from a specific device\n -p \t\tShow only logs from a specific process\n -r \tFilter messages by regular expression.\n -x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled).\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); return 1; } int c; From 5bee42c00c38589aef7d3825d7263458d4fdf5cd Mon Sep 17 00:00:00 2001 From: DanyL Date: Fri, 31 Jul 2015 21:01:45 +0300 Subject: [PATCH 06/13] Now using default Terminal.app colors for XCodeColors --- main.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/main.c b/main.c index 38de510..1d39b85 100644 --- a/main.c +++ b/main.c @@ -113,21 +113,21 @@ static unsigned char should_print_message(const char *buffer, size_t length) static void set_colors(xcode_colors) { COLOR_RESET = (xcode_colors) ? "\e[;" : "\e[m"; COLOR_NORMAL = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 0) : "\e[0m"; - COLOR_DARK = (xcode_colors) ? xcode_color_with_rgb("fg", 207, 201, 189) : "\e[2m"; - COLOR_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 31, 2) : "\e[0;31m"; - COLOR_DARK_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 148, 18, 1) : "\e[2;31m"; - COLOR_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 2, 255, 14) : "\e[0;32m"; - COLOR_DARK_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 1, 139, 8) : "\e[2;32m"; - COLOR_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 228, 0) : "\e[0;33m"; - COLOR_DARK_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 167, 149, 1) : "\e[2;33m"; - COLOR_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 255) : "\e[0;34m"; - COLOR_DARK_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 100) : "\e[2;34m"; - COLOR_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 213, 149, 139) : "\e[0;35m"; - COLOR_DARK_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 145, 100, 165) : "\e[2;35m"; - COLOR_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 45, 253, 255) : "\e[0;36m"; - COLOR_DARK_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 34, 129, 128) : "\e[2;36m"; - COLOR_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 255, 255, 255) : "\e[0;37m"; - COLOR_DARK_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 180, 180, 180) : "\e[0;37m"; + COLOR_DARK = (xcode_colors) ? xcode_color_with_rgb("fg", 102, 102, 102) : "\e[2m"; + COLOR_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 151, 4, 12) : "\e[0;31m"; + COLOR_DARK_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 227, 10, 23) : "\e[2;31m"; + COLOR_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 23, 164, 26) : "\e[0;32m"; + COLOR_DARK_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 33, 215, 38) : "\e[2;32m"; + COLOR_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 153, 152, 29) : "\e[0;33m"; + COLOR_DARK_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 229, 228, 49) : "\e[2;33m"; + COLOR_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 5, 22, 175) : "\e[0;34m"; + COLOR_DARK_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 11, 36, 251) : "\e[2;34m"; + COLOR_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 177, 25, 176) : "\e[0;35m"; + COLOR_DARK_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 227, 25, 227) : "\e[2;35m"; + COLOR_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 26, 166, 177) : "\e[0;36m"; + COLOR_DARK_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 39, 229, 228) : "\e[2;36m"; + COLOR_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 191, 191, 191) : "\e[0;37m"; + COLOR_DARK_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 230, 229, 230) : "\e[0;37m"; } static void write_colored(int fd, const char *buffer, size_t length) From 0719dcfb091621daa0b7a4ff82230c30ee3b648c Mon Sep 17 00:00:00 2001 From: DanyL Date: Sat, 1 Aug 2015 04:09:48 +0300 Subject: [PATCH 07/13] Added support for multi process filtering --- main.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/main.c b/main.c index 51afa6e..da410f2 100644 --- a/main.c +++ b/main.c @@ -13,7 +13,7 @@ typedef struct { static CFMutableDictionaryRef liveConnections; static int debug; static CFStringRef requiredDeviceId; -static char *requiredProcessName; +static char *requiredProcessNames; static regex_t *requiredRegex; static void (*printMessage)(int fd, const char *, size_t); static void (*printSeparator)(int fd); @@ -75,7 +75,8 @@ static unsigned char should_print_message(const char *buffer, size_t length) find_space_offsets(buffer, length, space_offsets); // Check whether process name matches the one passed to -p option and filter if needed - if (requiredProcessName != NULL) { + if (requiredProcessNames != NULL) { + char *currentProcessName; int nameLength = space_offsets[1] - space_offsets[0]; //This size includes the NULL terminator. char *processName = malloc(nameLength); @@ -86,8 +87,15 @@ static unsigned char should_print_message(const char *buffer, size_t length) if (processName[i] == '[') processName[i] = '\0'; - if (strcmp(processName, requiredProcessName) != 0) - should_print = 0; + currentProcessName = strtok(strdup(requiredProcessNames), ", "); + while (currentProcessName != NULL) { + should_print = (strcmp(processName, currentProcessName) == 0); + + if (should_print) + break; + + currentProcessName = strtok(NULL, ", "); + } free(processName); } @@ -321,7 +329,7 @@ static void color_separator(int fd) int main (int argc, char * const argv[]) { if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) { - fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\t\tInclude connect/disconnect messages in standard out\n -u \t\t\tShow only logs from a specific device\n -p \t\tShow only logs from a specific process\n -r \tFilter messages by regular expression.\n -x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled).\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); + fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\t\tInclude connect/disconnect messages in standard out\n -u \t\t\tShow only logs from a specific device\n -p <\"process name, process name\">\t\tShow only logs from a specific process\n -r \tFilter messages by regular expression.\n -x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled).\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); return 1; } int c; @@ -351,10 +359,10 @@ int main (int argc, char * const argv[]) requiredDeviceId = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingASCII); break; case 'p': - requiredProcessName = malloc(strlen(optarg) + 1); - requiredProcessName[strlen(optarg)] = '\0'; + requiredProcessNames = malloc(strlen(optarg) + 1); + requiredProcessNames[strlen(optarg)] = '\0'; - strcpy(requiredProcessName, optarg); + strcpy(requiredProcessNames, optarg); break; case 'r': requiredRegex = malloc(sizeof(regex_t)); From d3695afffd48838e6f83d565b26e2f9e744e6d4b Mon Sep 17 00:00:00 2001 From: "Dany DL. Lisiansky" Date: Sat, 31 Dec 2016 19:50:40 +0200 Subject: [PATCH 08/13] Bug fixes. PID filtering support. Process extension filtering support (kext/dylib) - *iOS 10 only* --- MobileDevice.framework | 1 - main.c | 173 ++++++++++++++++++++++++++++++++++------- 2 files changed, 143 insertions(+), 31 deletions(-) delete mode 120000 MobileDevice.framework diff --git a/MobileDevice.framework b/MobileDevice.framework deleted file mode 120000 index 40d3ede..0000000 --- a/MobileDevice.framework +++ /dev/null @@ -1 +0,0 @@ -/System/Library/PrivateFrameworks/MobileDevice.framework \ No newline at end of file diff --git a/main.c b/main.c index da410f2..254a65e 100644 --- a/main.c +++ b/main.c @@ -10,11 +10,19 @@ typedef struct { CFRunLoopSourceRef source; } DeviceConsoleConnection; +typedef struct { + char *name; + char *pid; + char *extension; +} ProcessParams, *ProcessParams_p; + static CFMutableDictionaryRef liveConnections; static int debug; static CFStringRef requiredDeviceId; static char *requiredProcessNames; -static regex_t *requiredRegex; +static char *requiredExtensionNames; +static bool use_regex = false; +static regex_t requiredRegex; static void (*printMessage)(int fd, const char *, size_t); static void (*printSeparator)(int fd); @@ -56,6 +64,9 @@ static int find_space_offsets(const char *buffer, size_t length, size_t *space_o { int o = 0; for (size_t i = 16; i < length; i++) { + if (buffer[i] == '\0') + break; + if (buffer[i] == ' ') { space_offsets_out[o++] = i; if (o == 3) { @@ -65,52 +76,125 @@ static int find_space_offsets(const char *buffer, size_t length, size_t *space_o } return o; } + + +/* ! Modifies buffer ! */ +static void parse_process_params(char *buffer, ProcessParams_p process_params_out) { + memset(process_params_out, 0, sizeof(ProcessParams)); + + process_params_out->name = buffer; + + for (int i = strlen(buffer); i != 0; i--) { + if (buffer[i] == ']') + buffer[i] = '\0'; + + if (buffer[i] == '[') { + process_params_out->pid = buffer + i + 1; + buffer[i] = '\0'; + } + + if (buffer[i] == ')') + buffer[i] = '\0'; + + if (buffer[i] == '(') { + process_params_out->extension = buffer + i + 1; + buffer[i] = '\0'; + } + } +} + static unsigned char should_print_message(const char *buffer, size_t length) { if (length < 3) return 0; // don't want blank lines + static unsigned char last_should_print = 0; unsigned char should_print = 1; size_t space_offsets[3]; find_space_offsets(buffer, length, space_offsets); - // Check whether process name matches the one passed to -p option and filter if needed - if (requiredProcessNames != NULL) { - char *currentProcessName; + + // Both process name/pid and extension name filters require process params parsing + if (requiredProcessNames != NULL || requiredExtensionNames != NULL) { int nameLength = space_offsets[1] - space_offsets[0]; //This size includes the NULL terminator. - char *processName = malloc(nameLength); - processName[nameLength - 1] = '\0'; - memcpy(processName, buffer + space_offsets[0] + 1, nameLength - 1); - - for (int i = strlen(processName); i != 0; i--) - if (processName[i] == '[') - processName[i] = '\0'; + char *allProcessParams = malloc(nameLength); + allProcessParams[nameLength - 1] = '\0'; - currentProcessName = strtok(strdup(requiredProcessNames), ", "); - while (currentProcessName != NULL) { - should_print = (strcmp(processName, currentProcessName) == 0); - - if (should_print) - break; + memcpy(allProcessParams, buffer + space_offsets[0] + 1, nameLength - 1); + + ProcessParams processParams; + parse_process_params(allProcessParams, &processParams); + + // Check whether process name matches the list passed to -p option and filter if needed + if (requiredProcessNames != NULL) { + char *currentProcessName = strtok(strdup(requiredProcessNames), ", "); + while (currentProcessName != NULL) { + bool isPID = (processParams.pid != NULL); + for (int i=0; i < strlen(currentProcessName); i++) { + if (isnumber(currentProcessName[i]) == 0) { + isPID = false; + break; + } + } + + should_print = (strcmp((isPID) ? processParams.pid : processParams.name, currentProcessName) == 0); + + if (should_print) + break; + + currentProcessName = strtok(NULL, ", "); + } - currentProcessName = strtok(NULL, ", "); + if (!should_print) { + last_should_print = should_print; + return should_print; + } } + + + // Check whether extension name matches the list passed to -e option and filter if needed + if (requiredExtensionNames != NULL) { + if (processParams.extension == NULL) { + last_should_print = false; + return false; + } + - free(processName); + char *currentExtensionName = strtok(strdup(requiredExtensionNames), ", "); + while (currentExtensionName != NULL) { + should_print = (strcmp(processParams.extension, currentExtensionName) == 0); + + if (should_print) + break; + + currentExtensionName = strtok(NULL, ", "); + } + + if (!should_print) { + last_should_print = should_print; + return should_print; + } + } + + free(allProcessParams); } - if (requiredRegex != NULL) { - char *message = malloc(length + 1); - memcpy(message, buffer, length + 1); + // Check whether buffer matches the regex passed to -r option and filter if needed + if (use_regex) { + char message[length + 1]; + + memcpy(message, buffer, length); message[length + 1] = '\0'; - if (regexec(requiredRegex, message, 0, NULL, 0) == REG_NOMATCH) - should_print = 0; + if (regexec(&requiredRegex, message, 0, NULL, 0) == REG_NOMATCH) + should_print = false; } + - // More filtering options can be added here and return 0 when they won't meed filter criteria + // More filtering options can be added here and return 0 when they won't meet filter criteria + last_should_print = should_print; return should_print; } @@ -223,8 +307,21 @@ static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef a while ((buffer[extentLength] != '\0') && extentLength != length) { extentLength++; } + + static unsigned char should_print_result = false; + bool should_filter = false; + + if ( strnstr(buffer, ":", 150) || strnstr(buffer, ":", 150) + || strnstr(buffer, ":", 150) || strnstr(buffer, ":", 150) + || strnstr(buffer, ":", 150) || strnstr(buffer, ":", 150)) + { + should_filter = true; + } + + if (should_filter) + should_print_result = should_print_message(buffer, extentLength); - if (should_print_message(buffer, extentLength)) { + if (should_print_result) { printMessage(1, buffer, extentLength); printSeparator(1); } @@ -329,7 +426,7 @@ static void color_separator(int fd) int main (int argc, char * const argv[]) { if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) { - fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\t\tInclude connect/disconnect messages in standard out\n -u \t\t\tShow only logs from a specific device\n -p <\"process name, process name\">\t\tShow only logs from a specific process\n -r \tFilter messages by regular expression.\n -x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled).\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); + fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\t\tInclude connect/disconnect messages in standard out\n -u \t\t\tShow only logs from a specific device\n -p <\"process name, pid\">\tShow only logs from a specific process name or pid\n -e <\"kext name, dylib name\">\tShow only logs from a specific process extension (kext/dylib) - *iOS 10 only*\n -r \tFilter messages by regular expression.\n -x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled).\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); return 1; } int c; @@ -338,7 +435,7 @@ int main (int argc, char * const argv[]) bool xcode_colors = ((getenv("XcodeColors")) ? strstr(getenv("XcodeColors"), "YES") != NULL : false); bool in_xcode = xcode_colors; - while ((c = getopt(argc, argv, "dcxsu:p:r:")) != -1) + while ((c = getopt(argc, argv, "dcxsu:p:r:e:")) != -1) switch (c) { case 'd': @@ -364,9 +461,15 @@ int main (int argc, char * const argv[]) strcpy(requiredProcessNames, optarg); break; + case 'e': + requiredExtensionNames = malloc(strlen(optarg) + 1); + requiredExtensionNames[strlen(optarg)] = '\0'; + + strcpy(requiredExtensionNames, optarg); + break; case 'r': - requiredRegex = malloc(sizeof(regex_t)); - if (regcomp(requiredRegex, optarg, REG_EXTENDED | REG_NEWLINE | REG_ICASE)) { + use_regex = true; + if (regcomp(&requiredRegex, optarg, REG_EXTENDED | REG_NEWLINE | REG_ICASE)) { fprintf(stderr, "Error: Could not compile regex %s.\n", optarg); return 1; } @@ -394,5 +497,15 @@ int main (int argc, char * const argv[]) am_device_notification *notification; AMDeviceNotificationSubscribe(DeviceNotificationCallback, 0, 0, NULL, ¬ification); CFRunLoopRun(); + + if (requiredProcessNames != NULL) + free(requiredProcessNames); + + if (requiredExtensionNames != NULL) + free(requiredExtensionNames); + + if (use_regex) + regfree(&requiredRegex); + return 0; } From 3c7619377bedd80d64f1798bc9691a44c5d5b5ba Mon Sep 17 00:00:00 2001 From: "Dany DL. Lisiansky" Date: Sun, 1 Jan 2017 13:09:08 +0200 Subject: [PATCH 09/13] Clean unused code. --- main.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/main.c b/main.c index 254a65e..ad043bd 100644 --- a/main.c +++ b/main.c @@ -107,7 +107,6 @@ static unsigned char should_print_message(const char *buffer, size_t length) { if (length < 3) return 0; // don't want blank lines - static unsigned char last_should_print = 0; unsigned char should_print = 1; size_t space_offsets[3]; @@ -146,20 +145,15 @@ static unsigned char should_print_message(const char *buffer, size_t length) currentProcessName = strtok(NULL, ", "); } - if (!should_print) { - last_should_print = should_print; + if (!should_print) return should_print; - } } // Check whether extension name matches the list passed to -e option and filter if needed if (requiredExtensionNames != NULL) { - if (processParams.extension == NULL) { - last_should_print = false; + if (processParams.extension == NULL) return false; - } - char *currentExtensionName = strtok(strdup(requiredExtensionNames), ", "); while (currentExtensionName != NULL) { @@ -171,10 +165,8 @@ static unsigned char should_print_message(const char *buffer, size_t length) currentExtensionName = strtok(NULL, ", "); } - if (!should_print) { - last_should_print = should_print; + if (!should_print) return should_print; - } } free(allProcessParams); @@ -194,7 +186,6 @@ static unsigned char should_print_message(const char *buffer, size_t length) // More filtering options can be added here and return 0 when they won't meet filter criteria - last_should_print = should_print; return should_print; } From 9b806a636cb6590e81b546253f4f1eb2f73b20c7 Mon Sep 17 00:00:00 2001 From: "Dany DL. Lisiansky" Date: Sun, 1 Jan 2017 23:03:34 +0200 Subject: [PATCH 10/13] Fix process name/PID highlighting and add support for highlighting process extension too (on iOS 10) --- main.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index ad043bd..2fbcbb1 100644 --- a/main.c +++ b/main.c @@ -227,19 +227,64 @@ static void write_colored(int fd, const char *buffer, size_t length) // Log date and device name write_const(fd, COLOR_DARK_WHITE); write_fully(fd, buffer, space_offsets[0]); - // Log process name + // Log process name, extension name and pid int pos = 0; - for (int i = space_offsets[0]; i < space_offsets[0]; i++) { + for (int i = space_offsets[0]; i < space_offsets[1]; i++) { + if (buffer[i] == '(') { + pos = i; + break; + } + if (buffer[i] == '[') { pos = i; break; } } write_const(fd, COLOR_CYAN); - if (pos && buffer[space_offsets[1]-1] == ']') { + if (pos) { + // Process name write_fully(fd, buffer + space_offsets[0], pos - space_offsets[0]); - write_const(fd, COLOR_DARK_CYAN); - write_fully(fd, buffer + pos, space_offsets[1] - pos); + + if (buffer[pos] == '(') { + // Find '[' too + + int new_pos = 0; + for (int i = space_offsets[0]; i < space_offsets[1]; i++) { + if (buffer[i] == '[') { + new_pos = i; + break; + } + } + + if (new_pos) { + // Process extension name + write_const(fd, COLOR_DARK_CYAN); + write_fully(fd, buffer + pos, 1); + write_const(fd, COLOR_CYAN); + write_fully(fd, buffer + pos + 1, new_pos - pos - 2); + write_const(fd, COLOR_DARK_CYAN); + write_fully(fd, buffer + new_pos - 1, 1); + + // PID + write_const(fd, COLOR_DARK_CYAN); + write_fully(fd, buffer + new_pos, 1); + write_const(fd, COLOR_CYAN); + write_fully(fd, buffer + new_pos + 1, space_offsets[1] - new_pos - 2); + write_const(fd, COLOR_DARK_CYAN); + write_fully(fd, buffer + space_offsets[1] - 1, 1); + } else { + write_fully(fd, buffer + pos, space_offsets[1] - pos); + } + + } else { + // PID + write_const(fd, COLOR_DARK_CYAN); + write_fully(fd, buffer + pos, 1); + write_const(fd, COLOR_CYAN); + write_fully(fd, buffer + pos + 1, space_offsets[1] - pos - 2); + write_const(fd, COLOR_DARK_CYAN); + write_fully(fd, buffer + space_offsets[1] - 1, 1); + } } else { write_fully(fd, buffer + space_offsets[0], space_offsets[1] - space_offsets[0]); } From 30236458dc643a6eda58e41e7a804cbfd705398f Mon Sep 17 00:00:00 2001 From: "Dany DL. Lisiansky" Date: Sun, 1 Jan 2017 23:16:02 +0200 Subject: [PATCH 11/13] Bug fix. --- main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 2fbcbb1..3f65f54 100644 --- a/main.c +++ b/main.c @@ -358,7 +358,11 @@ static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef a should_print_result = should_print_message(buffer, extentLength); if (should_print_result) { - printMessage(1, buffer, extentLength); + if (should_filter) + printMessage(1, buffer, extentLength); + else + write_fully(1, buffer, extentLength); + printSeparator(1); } From d5f7152b27ec8aaa8db605d93c983bf3d9af2406 Mon Sep 17 00:00:00 2001 From: "Dany DL. Lisiansky" Date: Sun, 1 Jan 2017 23:29:53 +0200 Subject: [PATCH 12/13] Fix separators with multi-lined messages (-s option) --- main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 3f65f54..a3c4b89 100644 --- a/main.c +++ b/main.c @@ -358,12 +358,17 @@ static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef a should_print_result = should_print_message(buffer, extentLength); if (should_print_result) { - if (should_filter) + if (should_filter) { + static bool is_first_message = true; + if (!is_first_message) + printSeparator(1); + else + is_first_message = false; + printMessage(1, buffer, extentLength); + } else write_fully(1, buffer, extentLength); - - printSeparator(1); } length -= extentLength; From bd4ba625f87706e792502aa59f6d3e6f3b70e2a2 Mon Sep 17 00:00:00 2001 From: "Dany DL. Lisiansky" Date: Mon, 2 Jan 2017 00:45:24 +0200 Subject: [PATCH 13/13] Cleaner code. Use Config and Colors structs from now on. --- deviceconsole.xcodeproj/project.pbxproj | 4 + main.c | 246 ++++++++++++------------ main.h | 46 +++++ 3 files changed, 172 insertions(+), 124 deletions(-) create mode 100644 main.h diff --git a/deviceconsole.xcodeproj/project.pbxproj b/deviceconsole.xcodeproj/project.pbxproj index 8ac9a7b..67577d7 100644 --- a/deviceconsole.xcodeproj/project.pbxproj +++ b/deviceconsole.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ /* Begin PBXFileReference section */ 08FB7796FE84155DC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 8B6CE20D1E19B11F003E38F4 /* main.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = ""; }; 8DD76FB20486AB0100D96B5E /* deviceconsole */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = deviceconsole; sourceTree = BUILT_PRODUCTS_DIR; }; 945855DB140EB622009DFEA5 /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MobileDevice.h; sourceTree = ""; }; 945856A9140EC3BA009DFEA5 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; @@ -61,6 +62,7 @@ children = ( 945855DB140EB622009DFEA5 /* MobileDevice.h */, 08FB7796FE84155DC02AAC07 /* main.c */, + 8B6CE20D1E19B11F003E38F4 /* main.h */, ); name = Source; sourceTree = ""; @@ -99,6 +101,8 @@ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + }; buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "deviceconsole" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; diff --git a/main.c b/main.c index a3c4b89..a5d6a06 100644 --- a/main.c +++ b/main.c @@ -1,48 +1,10 @@ #include #include #include -#include -#include "MobileDevice.h" +#include "main.h" -typedef struct { - service_conn_t connection; - CFSocketRef socket; - CFRunLoopSourceRef source; -} DeviceConsoleConnection; - -typedef struct { - char *name; - char *pid; - char *extension; -} ProcessParams, *ProcessParams_p; - -static CFMutableDictionaryRef liveConnections; -static int debug; -static CFStringRef requiredDeviceId; -static char *requiredProcessNames; -static char *requiredExtensionNames; -static bool use_regex = false; -static regex_t requiredRegex; -static void (*printMessage)(int fd, const char *, size_t); -static void (*printSeparator)(int fd); - -static char *COLOR_RESET = NULL; -static char *COLOR_NORMAL = NULL; -static char *COLOR_DARK = NULL; -static char *COLOR_RED = NULL; -static char *COLOR_DARK_RED = NULL; -static char *COLOR_GREEN = NULL; -static char *COLOR_DARK_GREEN = NULL; -static char *COLOR_YELLOW = NULL; -static char *COLOR_DARK_YELLOW = NULL; -static char *COLOR_BLUE = NULL; -static char *COLOR_DARK_BLUE = NULL; -static char *COLOR_MAGENTA = NULL; -static char *COLOR_DARK_MAGENTA = NULL; -static char *COLOR_CYAN = NULL; -static char *COLOR_DARK_CYAN = NULL; -static char *COLOR_WHITE = NULL; -static char *COLOR_DARK_WHITE = NULL; +static Config_p config = NULL; +static Colors_p colors = NULL; static inline void write_fully(int fd, const char *buffer, size_t length) { @@ -114,7 +76,7 @@ static unsigned char should_print_message(const char *buffer, size_t length) // Both process name/pid and extension name filters require process params parsing - if (requiredProcessNames != NULL || requiredExtensionNames != NULL) { + if (config->requiredProcessNames != NULL || config->requiredExtensionNames != NULL) { int nameLength = space_offsets[1] - space_offsets[0]; //This size includes the NULL terminator. char *allProcessParams = malloc(nameLength); @@ -126,8 +88,8 @@ static unsigned char should_print_message(const char *buffer, size_t length) parse_process_params(allProcessParams, &processParams); // Check whether process name matches the list passed to -p option and filter if needed - if (requiredProcessNames != NULL) { - char *currentProcessName = strtok(strdup(requiredProcessNames), ", "); + if (config->requiredProcessNames != NULL) { + char *currentProcessName = strtok(strdup(config->requiredProcessNames), ", "); while (currentProcessName != NULL) { bool isPID = (processParams.pid != NULL); for (int i=0; i < strlen(currentProcessName); i++) { @@ -151,11 +113,11 @@ static unsigned char should_print_message(const char *buffer, size_t length) // Check whether extension name matches the list passed to -e option and filter if needed - if (requiredExtensionNames != NULL) { + if (config->requiredExtensionNames != NULL) { if (processParams.extension == NULL) return false; - char *currentExtensionName = strtok(strdup(requiredExtensionNames), ", "); + char *currentExtensionName = strtok(strdup(config->requiredExtensionNames), ", "); while (currentExtensionName != NULL) { should_print = (strcmp(processParams.extension, currentExtensionName) == 0); @@ -173,13 +135,13 @@ static unsigned char should_print_message(const char *buffer, size_t length) } // Check whether buffer matches the regex passed to -r option and filter if needed - if (use_regex) { + if (config->use_regex) { char message[length + 1]; memcpy(message, buffer, length); message[length + 1] = '\0'; - if (regexec(&requiredRegex, message, 0, NULL, 0) == REG_NOMATCH) + if (regexec(&config->requiredRegex, message, 0, NULL, 0) == REG_NOMATCH) should_print = false; } @@ -193,24 +155,24 @@ static unsigned char should_print_message(const char *buffer, size_t length) #define stringify(x) #x #define xcode_color_with_rgb(type, r, g, b) "\e[" type stringify(r) "," stringify(g) "," stringify(b) ";" -static void set_colors(xcode_colors) { - COLOR_RESET = (xcode_colors) ? "\e[;" : "\e[m"; - COLOR_NORMAL = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 0) : "\e[0m"; - COLOR_DARK = (xcode_colors) ? xcode_color_with_rgb("fg", 102, 102, 102) : "\e[2m"; - COLOR_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 151, 4, 12) : "\e[0;31m"; - COLOR_DARK_RED = (xcode_colors) ? xcode_color_with_rgb("fg", 227, 10, 23) : "\e[2;31m"; - COLOR_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 23, 164, 26) : "\e[0;32m"; - COLOR_DARK_GREEN = (xcode_colors) ? xcode_color_with_rgb("fg", 33, 215, 38) : "\e[2;32m"; - COLOR_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 153, 152, 29) : "\e[0;33m"; - COLOR_DARK_YELLOW = (xcode_colors) ? xcode_color_with_rgb("fg", 229, 228, 49) : "\e[2;33m"; - COLOR_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 5, 22, 175) : "\e[0;34m"; - COLOR_DARK_BLUE = (xcode_colors) ? xcode_color_with_rgb("fg", 11, 36, 251) : "\e[2;34m"; - COLOR_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 177, 25, 176) : "\e[0;35m"; - COLOR_DARK_MAGENTA = (xcode_colors) ? xcode_color_with_rgb("fg", 227, 25, 227) : "\e[2;35m"; - COLOR_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 26, 166, 177) : "\e[0;36m"; - COLOR_DARK_CYAN = (xcode_colors) ? xcode_color_with_rgb("fg", 39, 229, 228) : "\e[2;36m"; - COLOR_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 191, 191, 191) : "\e[0;37m"; - COLOR_DARK_WHITE = (xcode_colors) ? xcode_color_with_rgb("fg", 230, 229, 230) : "\e[0;37m"; +static void set_colors(bool xcode_colors) { + colors->reset = (xcode_colors) ? "\e[;" : "\e[m"; + colors->normal = (xcode_colors) ? xcode_color_with_rgb("fg", 0, 0, 0) : "\e[0m"; + colors->dark = (xcode_colors) ? xcode_color_with_rgb("fg", 102, 102, 102) : "\e[2m"; + colors->red = (xcode_colors) ? xcode_color_with_rgb("fg", 151, 4, 12) : "\e[0;31m"; + colors->dark_red = (xcode_colors) ? xcode_color_with_rgb("fg", 227, 10, 23) : "\e[2;31m"; + colors->green = (xcode_colors) ? xcode_color_with_rgb("fg", 23, 164, 26) : "\e[0;32m"; + colors->dark_green = (xcode_colors) ? xcode_color_with_rgb("fg", 33, 215, 38) : "\e[2;32m"; + colors->yellow = (xcode_colors) ? xcode_color_with_rgb("fg", 153, 152, 29) : "\e[0;33m"; + colors->dark_yellow = (xcode_colors) ? xcode_color_with_rgb("fg", 229, 228, 49) : "\e[2;33m"; + colors->blue = (xcode_colors) ? xcode_color_with_rgb("fg", 5, 22, 175) : "\e[0;34m"; + colors->dark_blue = (xcode_colors) ? xcode_color_with_rgb("fg", 11, 36, 251) : "\e[2;34m"; + colors->magenta = (xcode_colors) ? xcode_color_with_rgb("fg", 177, 25, 176) : "\e[0;35m"; + colors->dark_magenta = (xcode_colors) ? xcode_color_with_rgb("fg", 227, 25, 227) : "\e[2;35m"; + colors->cyan = (xcode_colors) ? xcode_color_with_rgb("fg", 26, 166, 177) : "\e[0;36m"; + colors->dark_cyan = (xcode_colors) ? xcode_color_with_rgb("fg", 39, 229, 228) : "\e[2;36m"; + colors->white = (xcode_colors) ? xcode_color_with_rgb("fg", 191, 191, 191) : "\e[0;37m"; + colors->dark_white = (xcode_colors) ? xcode_color_with_rgb("fg", 230, 229, 230) : "\e[0;37m"; } static void write_colored(int fd, const char *buffer, size_t length) @@ -225,7 +187,7 @@ static void write_colored(int fd, const char *buffer, size_t length) if (o == 3) { // Log date and device name - write_const(fd, COLOR_DARK_WHITE); + write_const(fd, colors->dark_white); write_fully(fd, buffer, space_offsets[0]); // Log process name, extension name and pid int pos = 0; @@ -240,7 +202,7 @@ static void write_colored(int fd, const char *buffer, size_t length) break; } } - write_const(fd, COLOR_CYAN); + write_const(fd, colors->cyan); if (pos) { // Process name write_fully(fd, buffer + space_offsets[0], pos - space_offsets[0]); @@ -258,19 +220,19 @@ static void write_colored(int fd, const char *buffer, size_t length) if (new_pos) { // Process extension name - write_const(fd, COLOR_DARK_CYAN); + write_const(fd, colors->dark_cyan); write_fully(fd, buffer + pos, 1); - write_const(fd, COLOR_CYAN); + write_const(fd, colors->cyan); write_fully(fd, buffer + pos + 1, new_pos - pos - 2); - write_const(fd, COLOR_DARK_CYAN); + write_const(fd, colors->dark_cyan); write_fully(fd, buffer + new_pos - 1, 1); // PID - write_const(fd, COLOR_DARK_CYAN); + write_const(fd, colors->dark_cyan); write_fully(fd, buffer + new_pos, 1); - write_const(fd, COLOR_CYAN); + write_const(fd, colors->cyan); write_fully(fd, buffer + new_pos + 1, space_offsets[1] - new_pos - 2); - write_const(fd, COLOR_DARK_CYAN); + write_const(fd, colors->dark_cyan); write_fully(fd, buffer + space_offsets[1] - 1, 1); } else { write_fully(fd, buffer + pos, space_offsets[1] - pos); @@ -278,11 +240,11 @@ static void write_colored(int fd, const char *buffer, size_t length) } else { // PID - write_const(fd, COLOR_DARK_CYAN); + write_const(fd, colors->dark_cyan); write_fully(fd, buffer + pos, 1); - write_const(fd, COLOR_CYAN); + write_const(fd, colors->cyan); write_fully(fd, buffer + pos + 1, space_offsets[1] - pos - 2); - write_const(fd, COLOR_DARK_CYAN); + write_const(fd, colors->dark_cyan); write_fully(fd, buffer + space_offsets[1] - 1, 1); } } else { @@ -294,17 +256,17 @@ static void write_colored(int fd, const char *buffer, size_t length) const char *normalColor; const char *darkColor; if (levelLength == 9 && memcmp(buffer + space_offsets[1], " :", 9) == 0){ - normalColor = COLOR_MAGENTA; - darkColor = COLOR_DARK_MAGENTA; + normalColor = colors->magenta; + darkColor = colors->dark_magenta; } else if (levelLength == 11 && memcmp(buffer + space_offsets[1], " :", 11) == 0){ - normalColor = COLOR_YELLOW; - darkColor = COLOR_DARK_YELLOW; + normalColor = colors->yellow; + darkColor = colors->dark_yellow; } else if (levelLength == 9 && memcmp(buffer + space_offsets[1], " :", 9) == 0){ - normalColor = COLOR_RED; - darkColor = COLOR_DARK_RED; + normalColor = colors->red; + darkColor = colors->dark_red; } else if (levelLength == 10 && memcmp(buffer + space_offsets[1], " :", 10) == 0) { - normalColor = COLOR_GREEN; - darkColor = COLOR_DARK_GREEN; + normalColor = colors->green; + darkColor = colors->dark_green; } else { goto level_unformatted; } @@ -314,14 +276,14 @@ static void write_colored(int fd, const char *buffer, size_t length) write_fully(fd, buffer + space_offsets[1] + 2, levelLength - 4); write_string(fd, darkColor); write_fully(fd, buffer + space_offsets[1] + levelLength - 2, 1); - write_const(fd, COLOR_DARK_WHITE); + write_const(fd, colors->dark_white); write_fully(fd, buffer + space_offsets[1] + levelLength - 1, 1); } else { level_unformatted: - write_const(fd, COLOR_RESET); + write_const(fd, colors->reset); write_fully(fd, buffer + space_offsets[1], levelLength); } - write_const(fd, COLOR_RESET); + write_const(fd, colors->reset); write_fully(fd, buffer + space_offsets[2], length - space_offsets[2]); } else { write_fully(fd, buffer, length); @@ -361,11 +323,11 @@ static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef a if (should_filter) { static bool is_first_message = true; if (!is_first_message) - printSeparator(1); + config->printSeparator(1); else is_first_message = false; - printMessage(1, buffer, extentLength); + config->printMessage(1, buffer, extentLength); } else write_fully(1, buffer, extentLength); @@ -381,16 +343,16 @@ static void DeviceNotificationCallback(am_device_notification_callback_info *inf struct am_device *device = info->dev; switch (info->msg) { case ADNCI_MSG_CONNECTED: { - if (debug) { + if (config->debug) { CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); CFStringRef str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("deviceconsole connected: %@"), deviceId); CFRelease(deviceId); CFShow(str); CFRelease(str); } - if (requiredDeviceId) { + if (config->requiredDeviceId) { CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); - Boolean isRequiredDevice = CFEqual(deviceId, requiredDeviceId); + Boolean isRequiredDevice = CFEqual(deviceId, config->requiredDeviceId); CFRelease(deviceId); if (!isRequiredDevice) break; @@ -410,7 +372,7 @@ static void DeviceNotificationCallback(am_device_notification_callback_info *inf data->connection = connection; data->socket = socket; data->source = source; - CFDictionarySetValue(liveConnections, device, data); + CFDictionarySetValue(config->liveConnections, device, data); return; } CFRelease(source); @@ -424,16 +386,16 @@ static void DeviceNotificationCallback(am_device_notification_callback_info *inf break; } case ADNCI_MSG_DISCONNECTED: { - if (debug) { + if (config->debug) { CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); CFStringRef str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("deviceconsole disconnected: %@"), deviceId); CFRelease(deviceId); CFShow(str); CFRelease(str); } - DeviceConsoleConnection *data = (DeviceConsoleConnection *)CFDictionaryGetValue(liveConnections, device); + DeviceConsoleConnection *data = (DeviceConsoleConnection *)CFDictionaryGetValue(config->liveConnections, device); if (data) { - CFDictionaryRemoveValue(liveConnections, device); + CFDictionaryRemoveValue(config->liveConnections, device); AMDeviceRelease(device); CFRunLoopRemoveSource(CFRunLoopGetMain(), data->source, kCFRunLoopCommonModes); CFRelease(data->source); @@ -460,20 +422,48 @@ static void plain_separator(int fd) static void color_separator(int fd) { - size_t buffer_lentgh = sizeof(char) * (strlen(COLOR_DARK_WHITE) + strlen(COLOR_RESET) + 3); + size_t buffer_lentgh = sizeof(char) * (strlen(colors->dark_white) + strlen(colors->reset) + 3); char *buffer = malloc(buffer_lentgh); - sprintf(buffer, "%s--%s\n", COLOR_DARK_WHITE, COLOR_RESET); + sprintf(buffer, "%s--%s\n", colors->dark_white, colors->reset); write_const(fd, buffer); free(buffer); } +static void print_help(char *process_name) { + fprintf(stderr, + "Usage: %s [options]\n" + "Options:\n" + " -d\t\t\t\tInclude connect/disconnect messages in standard out" + "\n" + " -u \t\t\tShow only logs from a specific device" + "\n" + "-p <\"process name, pid\">\tShow only logs from a specific process name or pid" + "\n" + "-e <\"kext name, dylib name\">\tShow only logs from a specific process extension (kext/dylib) - *iOS 10 only*" + "\n" + "-r \tFilter messages by regular expression." + "\n" + "-x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled)." + "\n" + "\n" + "Control-C to disconnect" + "\n" + "Mail bug reports and suggestions to (or )" + "\n" + , process_name); +} + int main (int argc, char * const argv[]) { - if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) { - fprintf(stderr, "Usage: %s [options]\nOptions:\n -d\t\t\t\tInclude connect/disconnect messages in standard out\n -u \t\t\tShow only logs from a specific device\n -p <\"process name, pid\">\tShow only logs from a specific process name or pid\n -e <\"kext name, dylib name\">\tShow only logs from a specific process extension (kext/dylib) - *iOS 10 only*\n -r \tFilter messages by regular expression.\n -x\t\t\t\tDisable tty coloring in Xcode (unless XcodeColors intalled).\n\nControl-C to disconnect\nMail bug reports and suggestions to \n", argv[0]); + if ((argc == 2) && ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0))) { + print_help(argv[0]); return 1; } + + config = malloc(sizeof(Config)); + memset(config, 0, sizeof(Config)); + int c; bool use_separators = false; bool force_color = isatty(1); @@ -484,7 +474,7 @@ int main (int argc, char * const argv[]) switch (c) { case 'd': - debug = 1; + config->debug = 1; break; case 'c': force_color = true; @@ -496,25 +486,25 @@ int main (int argc, char * const argv[]) use_separators = true; break; case 'u': - if (requiredDeviceId) - CFRelease(requiredDeviceId); - requiredDeviceId = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingASCII); + if (config->requiredDeviceId) + CFRelease(config->requiredDeviceId); + config->requiredDeviceId = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingASCII); break; case 'p': - requiredProcessNames = malloc(strlen(optarg) + 1); - requiredProcessNames[strlen(optarg)] = '\0'; + config->requiredProcessNames = malloc(strlen(optarg) + 1); + config->requiredProcessNames[strlen(optarg)] = '\0'; - strcpy(requiredProcessNames, optarg); + strcpy(config->requiredProcessNames, optarg); break; case 'e': - requiredExtensionNames = malloc(strlen(optarg) + 1); - requiredExtensionNames[strlen(optarg)] = '\0'; + config->requiredExtensionNames = malloc(strlen(optarg) + 1); + config->requiredExtensionNames[strlen(optarg)] = '\0'; - strcpy(requiredExtensionNames, optarg); + strcpy(config->requiredExtensionNames, optarg); break; case 'r': - use_regex = true; - if (regcomp(&requiredRegex, optarg, REG_EXTENDED | REG_NEWLINE | REG_ICASE)) { + config->use_regex = true; + if (regcomp(&config->requiredRegex, optarg, REG_EXTENDED | REG_NEWLINE | REG_ICASE)) { fprintf(stderr, "Error: Could not compile regex %s.\n", optarg); return 1; } @@ -531,26 +521,34 @@ int main (int argc, char * const argv[]) abort(); } if ((!in_xcode && force_color) || xcode_colors) { + colors = malloc(sizeof(Colors)); set_colors(xcode_colors); - printMessage = &write_colored; - printSeparator = use_separators ? &color_separator : &no_separator; + + config->printMessage = &write_colored; + config->printSeparator = use_separators ? &color_separator : &no_separator; } else { - printMessage = &write_fully; - printSeparator = use_separators ? &plain_separator : &no_separator; + config->printMessage = &write_fully; + config->printSeparator = use_separators ? &plain_separator : &no_separator; } - liveConnections = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); + config->liveConnections = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); am_device_notification *notification; AMDeviceNotificationSubscribe(DeviceNotificationCallback, 0, 0, NULL, ¬ification); CFRunLoopRun(); - if (requiredProcessNames != NULL) - free(requiredProcessNames); + if (config->requiredProcessNames != NULL) + free(config->requiredProcessNames); + + if (config->requiredExtensionNames != NULL) + free(config->requiredExtensionNames); + + if (config->use_regex) + regfree(&config->requiredRegex); - if (requiredExtensionNames != NULL) - free(requiredExtensionNames); + if (config != NULL) + free(config); - if (use_regex) - regfree(&requiredRegex); + if (colors != NULL) + free(colors); return 0; } diff --git a/main.h b/main.h new file mode 100644 index 0000000..1cb3bb7 --- /dev/null +++ b/main.h @@ -0,0 +1,46 @@ +#include +#include "MobileDevice.h" + +typedef struct { + service_conn_t connection; + CFSocketRef socket; + CFRunLoopSourceRef source; +} DeviceConsoleConnection; + +typedef struct { + char *name; + char *pid; + char *extension; +} ProcessParams, *ProcessParams_p; + +typedef struct { + char *reset; + char *normal; + char *dark; + char *red; + char *dark_red; + char *green; + char *dark_green; + char *yellow; + char *dark_yellow; + char *blue; + char *dark_blue; + char *magenta; + char *dark_magenta; + char *cyan; + char *dark_cyan; + char *white; + char *dark_white; +} Colors, *Colors_p; + +typedef struct { + int debug; + CFMutableDictionaryRef liveConnections; + CFStringRef requiredDeviceId; + char *requiredProcessNames; + char *requiredExtensionNames; + bool use_regex; + regex_t requiredRegex; + void (*printMessage)(int fd, const char *, size_t); + void (*printSeparator)(int fd); +} Config, *Config_p;