diff options
Diffstat (limited to 'tools/idevicesyslog.c')
| -rw-r--r-- | tools/idevicesyslog.c | 506 |
1 files changed, 499 insertions, 7 deletions
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c index 619b51b..b3a754f 100644 --- a/tools/idevicesyslog.c +++ b/tools/idevicesyslog.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * idevicesyslog.c | 2 | * idevicesyslog.c |
| 3 | * Relay the syslog of a device to stdout | 3 | * Relay the syslog of a device to stdout |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. | 5 | * Copyright (c) 2010-2020 Nikias Bassen, All Rights Reserved. |
| 6 | * Copyright (c) 2009 Martin Szulecki All Rights Reserved. | 6 | * Copyright (c) 2009 Martin Szulecki All Rights Reserved. |
| 7 | * | 7 | * |
| 8 | * This library is free software; you can redistribute it and/or | 8 | * This library is free software; you can redistribute it and/or |
| @@ -42,19 +42,325 @@ | |||
| 42 | 42 | ||
| 43 | static int quit_flag = 0; | 43 | static int quit_flag = 0; |
| 44 | static int exit_on_disconnect = 0; | 44 | static int exit_on_disconnect = 0; |
| 45 | static int use_colors = 0; | ||
| 46 | static int show_device_name = 0; | ||
| 45 | 47 | ||
| 46 | static char* udid = NULL; | 48 | static char* udid = NULL; |
| 49 | static char** proc_filters = NULL; | ||
| 50 | static int num_proc_filters = 0; | ||
| 51 | static int proc_filter_excluding = 0; | ||
| 52 | |||
| 53 | static int* pid_filters = NULL; | ||
| 54 | static int num_pid_filters = 0; | ||
| 55 | |||
| 56 | static char** msg_filters = NULL; | ||
| 57 | static int num_msg_filters = 0; | ||
| 58 | |||
| 59 | static char** trigger_filters = NULL; | ||
| 60 | static int num_trigger_filters = 0; | ||
| 61 | static char** untrigger_filters = NULL; | ||
| 62 | static int num_untrigger_filters = 0; | ||
| 63 | static int triggered = 0; | ||
| 47 | 64 | ||
| 48 | static idevice_t device = NULL; | 65 | static idevice_t device = NULL; |
| 49 | static syslog_relay_client_t syslog = NULL; | 66 | static syslog_relay_client_t syslog = NULL; |
| 50 | 67 | ||
| 68 | static const char QUIET_FILTER[] = "CommCenter|SpringBoard|UserEventAgent|WirelessRadioManagerd|aggregated|appstored|backboardd|biometrickitd|bluetoothd|callservicesd|contextstored|corespeechd|dasd|gpsd|homed|identityservicesd|itunesstored|kernel|locationd|mDNSResponder|mediaremoted|mediaserverd|navd|nsurlsessiond|powerd|rapportd|routined|runningboardd|sharingd|symptomsd|thermalmonitord|useractivityd|wifid"; | ||
| 69 | |||
| 51 | enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK; | 70 | enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK; |
| 52 | 71 | ||
| 72 | static char *line = NULL; | ||
| 73 | static int line_buffer_size = 0; | ||
| 74 | static int lp = 0; | ||
| 75 | |||
| 76 | #define COLOR_RESET "\e[m" | ||
| 77 | #define COLOR_NORMAL "\e[0m" | ||
| 78 | #define COLOR_DARK "\e[2m" | ||
| 79 | #define COLOR_RED "\e[0;31m" | ||
| 80 | #define COLOR_DARK_RED "\e[2;31m" | ||
| 81 | #define COLOR_GREEN "\e[0;32m" | ||
| 82 | #define COLOR_DARK_GREEN "\e[2;32m" | ||
| 83 | #define COLOR_YELLOW "\e[0;33m" | ||
| 84 | #define COLOR_DARK_YELLOW "\e[2;33m" | ||
| 85 | #define COLOR_BLUE "\e[0;34m" | ||
| 86 | #define COLOR_DARK_BLUE "\e[2;34m" | ||
| 87 | #define COLOR_MAGENTA "\e[0;35m" | ||
| 88 | #define COLOR_DARK_MAGENTA "\e[2;35m" | ||
| 89 | #define COLOR_CYAN "\e[0;36m" | ||
| 90 | #define COLOR_BRIGHT_CYAN "\e[1;36m" | ||
| 91 | #define COLOR_DARK_CYAN "\e[2;36m" | ||
| 92 | #define COLOR_WHITE "\e[1;37m" | ||
| 93 | #define COLOR_DARK_WHITE "\e[0;37m" | ||
| 94 | |||
| 95 | #define TEXT_COLOR(x) if (use_colors) { fwrite(x, 1, sizeof(x), stdout); } | ||
| 96 | |||
| 97 | static void add_filter(const char* filterstr) | ||
| 98 | { | ||
| 99 | int filter_len = strlen(filterstr); | ||
| 100 | const char* start = filterstr; | ||
| 101 | const char* end = filterstr + filter_len; | ||
| 102 | const char* p = start; | ||
| 103 | while (p <= end) { | ||
| 104 | if ((*p == '|') || (*p == '\0')) { | ||
| 105 | if (p-start > 0) { | ||
| 106 | char* procn = malloc(p-start+1); | ||
| 107 | if (!procn) { | ||
| 108 | fprintf(stderr, "ERROR: malloc() failed\n"); | ||
| 109 | exit(EXIT_FAILURE); | ||
| 110 | } | ||
| 111 | memcpy(procn, start, p-start); | ||
| 112 | procn[p-start] = '\0'; | ||
| 113 | char* endp = NULL; | ||
| 114 | int pid_value = (int)strtol(procn, &endp, 10); | ||
| 115 | if (!endp || *endp == 0) { | ||
| 116 | int *new_pid_filters = realloc(pid_filters, sizeof(int) * (num_pid_filters+1)); | ||
| 117 | if (!new_pid_filters) { | ||
| 118 | fprintf(stderr, "ERROR: realloc() failed\n"); | ||
| 119 | exit(EXIT_FAILURE); | ||
| 120 | } | ||
| 121 | pid_filters = new_pid_filters; | ||
| 122 | pid_filters[num_pid_filters] = pid_value; | ||
| 123 | num_pid_filters++; | ||
| 124 | } else { | ||
| 125 | char **new_proc_filters = realloc(proc_filters, sizeof(char*) * (num_proc_filters+1)); | ||
| 126 | if (!new_proc_filters) { | ||
| 127 | fprintf(stderr, "ERROR: realloc() failed\n"); | ||
| 128 | exit(EXIT_FAILURE); | ||
| 129 | } | ||
| 130 | proc_filters = new_proc_filters; | ||
| 131 | proc_filters[num_proc_filters] = procn; | ||
| 132 | num_proc_filters++; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | start = p+1; | ||
| 136 | } | ||
| 137 | p++; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | static int find_char(char c, char** p, char* end) | ||
| 142 | { | ||
| 143 | while ((**p != c) && (*p < end)) { | ||
| 144 | (*p)++; | ||
| 145 | } | ||
| 146 | return (**p == c); | ||
| 147 | } | ||
| 148 | |||
| 149 | static void stop_logging(void); | ||
| 150 | |||
| 53 | static void syslog_callback(char c, void *user_data) | 151 | static void syslog_callback(char c, void *user_data) |
| 54 | { | 152 | { |
| 55 | putchar(c); | 153 | if (lp >= line_buffer_size-1) { |
| 56 | if (c == '\n') { | 154 | line_buffer_size+=1024; |
| 57 | fflush(stdout); | 155 | char* _line = realloc(line, line_buffer_size); |
| 156 | if (!_line) { | ||
| 157 | fprintf(stderr, "ERROR: realloc failed\n"); | ||
| 158 | exit(EXIT_FAILURE); | ||
| 159 | } | ||
| 160 | line = _line; | ||
| 161 | } | ||
| 162 | line[lp++] = c; | ||
| 163 | if (c == '\0') { | ||
| 164 | int shall_print = 0; | ||
| 165 | int trigger_off = 0; | ||
| 166 | lp--; | ||
| 167 | char* linep = &line[0]; | ||
| 168 | do { | ||
| 169 | if (lp < 16) { | ||
| 170 | shall_print = 1; | ||
| 171 | TEXT_COLOR(COLOR_WHITE); | ||
| 172 | break; | ||
| 173 | } else if (line[3] == ' ' && line[6] == ' ' && line[15] == ' ') { | ||
| 174 | char* end = &line[lp]; | ||
| 175 | char* p = &line[16]; | ||
| 176 | |||
| 177 | /* device name */ | ||
| 178 | char* device_name_start = p; | ||
| 179 | char* device_name_end = p; | ||
| 180 | if (!find_char(' ', &p, end)) break; | ||
| 181 | device_name_end = p; | ||
| 182 | p++; | ||
| 183 | |||
| 184 | /* check if we have any triggers/untriggers */ | ||
| 185 | if (num_untrigger_filters > 0 && triggered) { | ||
| 186 | int found = 0; | ||
| 187 | int i; | ||
| 188 | for (i = 0; i < num_untrigger_filters; i++) { | ||
| 189 | if (strstr(device_name_end+1, untrigger_filters[i])) { | ||
| 190 | found = 1; | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | if (!found) { | ||
| 195 | shall_print = 1; | ||
| 196 | } else { | ||
| 197 | shall_print = 1; | ||
| 198 | trigger_off = 1; | ||
| 199 | } | ||
| 200 | } else if (num_trigger_filters > 0 && !triggered) { | ||
| 201 | int found = 0; | ||
| 202 | int i; | ||
| 203 | for (i = 0; i < num_trigger_filters; i++) { | ||
| 204 | if (strstr(device_name_end+1, trigger_filters[i])) { | ||
| 205 | found = 1; | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | if (!found) { | ||
| 210 | shall_print = 0; | ||
| 211 | break; | ||
| 212 | } else { | ||
| 213 | triggered = 1; | ||
| 214 | shall_print = 1; | ||
| 215 | } | ||
| 216 | } else if (num_trigger_filters == 0 && num_untrigger_filters > 0 && !triggered) { | ||
| 217 | shall_print = 0; | ||
| 218 | quit_flag++; | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* check message filters */ | ||
| 223 | if (num_msg_filters > 0) { | ||
| 224 | int found = 0; | ||
| 225 | int i; | ||
| 226 | for (i = 0; i < num_msg_filters; i++) { | ||
| 227 | if (strstr(device_name_end+1, msg_filters[i])) { | ||
| 228 | found = 1; | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | if (!found) { | ||
| 233 | shall_print = 0; | ||
| 234 | break; | ||
| 235 | } else { | ||
| 236 | shall_print = 1; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | /* process name */ | ||
| 241 | char* proc_name_start = p; | ||
| 242 | char* proc_name_end = p; | ||
| 243 | if (!find_char('[', &p, end)) break; | ||
| 244 | char* process_name_start = proc_name_start; | ||
| 245 | char* process_name_end = p; | ||
| 246 | char* pid_start = p+1; | ||
| 247 | char* pp = process_name_start; | ||
| 248 | if (find_char('(', &pp, p)) { | ||
| 249 | process_name_end = pp; | ||
| 250 | } | ||
| 251 | if (!find_char(']', &p, end)) break; | ||
| 252 | p++; | ||
| 253 | if (*p != ' ') break; | ||
| 254 | proc_name_end = p; | ||
| 255 | p++; | ||
| 256 | |||
| 257 | int proc_matched = 0; | ||
| 258 | if (num_pid_filters > 0) { | ||
| 259 | char* endp = NULL; | ||
| 260 | int pid_value = (int)strtol(pid_start, &endp, 10); | ||
| 261 | if (endp && (*endp == ']')) { | ||
| 262 | int found = proc_filter_excluding; | ||
| 263 | int i = 0; | ||
| 264 | for (i = 0; i < num_pid_filters; i++) { | ||
| 265 | if (pid_value == pid_filters[i]) { | ||
| 266 | found = !proc_filter_excluding; | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | if (found) { | ||
| 271 | proc_matched = 1; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | } | ||
| 275 | if (num_proc_filters > 0 && !proc_matched) { | ||
| 276 | int found = proc_filter_excluding; | ||
| 277 | int i = 0; | ||
| 278 | for (i = 0; i < num_proc_filters; i++) { | ||
| 279 | if (!proc_filters[i]) continue; | ||
| 280 | if (strncmp(proc_filters[i], process_name_start, process_name_end-process_name_start) == 0) { | ||
| 281 | found = !proc_filter_excluding; | ||
| 282 | break; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | if (found) { | ||
| 286 | proc_matched = 1; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | if (proc_matched) { | ||
| 290 | shall_print = 1; | ||
| 291 | } else { | ||
| 292 | if (num_pid_filters > 0 || num_proc_filters > 0) { | ||
| 293 | shall_print = 0; | ||
| 294 | break; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | /* log level */ | ||
| 299 | char* level_start = p; | ||
| 300 | char* level_end = p; | ||
| 301 | const char* level_color = NULL; | ||
| 302 | if (!strncmp(p, "<Notice>:", 9)) { | ||
| 303 | level_end += 9; | ||
| 304 | level_color = COLOR_GREEN; | ||
| 305 | } else if (!strncmp(p, "<Error>:", 8)) { | ||
| 306 | level_end += 8; | ||
| 307 | level_color = COLOR_RED; | ||
| 308 | } else if (!strncmp(p, "<Warning>:", 10)) { | ||
| 309 | level_end += 10; | ||
| 310 | level_color = COLOR_YELLOW; | ||
| 311 | } else if (!strncmp(p, "<Debug>:", 8)) { | ||
| 312 | level_end += 8; | ||
| 313 | level_color = COLOR_MAGENTA; | ||
| 314 | } else { | ||
| 315 | level_color = COLOR_WHITE; | ||
| 316 | } | ||
| 317 | |||
| 318 | /* write date and time */ | ||
| 319 | TEXT_COLOR(COLOR_DARK_WHITE); | ||
| 320 | fwrite(line, 1, 16, stdout); | ||
| 321 | |||
| 322 | if (show_device_name) { | ||
| 323 | /* write device name */ | ||
| 324 | TEXT_COLOR(COLOR_DARK_YELLOW); | ||
| 325 | fwrite(device_name_start, 1, device_name_end-device_name_start+1, stdout); | ||
| 326 | TEXT_COLOR(COLOR_RESET); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* write process name */ | ||
| 330 | TEXT_COLOR(COLOR_BRIGHT_CYAN); | ||
| 331 | fwrite(process_name_start, 1, process_name_end-process_name_start, stdout); | ||
| 332 | TEXT_COLOR(COLOR_CYAN); | ||
| 333 | fwrite(process_name_end, 1, proc_name_end-process_name_end+1, stdout); | ||
| 334 | |||
| 335 | /* write log level */ | ||
| 336 | TEXT_COLOR(level_color); | ||
| 337 | if (level_end > level_start) { | ||
| 338 | fwrite(level_start, 1, level_end-level_start, stdout); | ||
| 339 | p = level_end; | ||
| 340 | } | ||
| 341 | |||
| 342 | lp -= p - linep; | ||
| 343 | linep = p; | ||
| 344 | |||
| 345 | TEXT_COLOR(COLOR_WHITE); | ||
| 346 | |||
| 347 | } else { | ||
| 348 | shall_print = 1; | ||
| 349 | TEXT_COLOR(COLOR_WHITE); | ||
| 350 | } | ||
| 351 | } while (0); | ||
| 352 | |||
| 353 | if ((num_msg_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) { | ||
| 354 | fwrite(linep, 1, lp, stdout); | ||
| 355 | TEXT_COLOR(COLOR_RESET); | ||
| 356 | fflush(stdout); | ||
| 357 | if (trigger_off) { | ||
| 358 | triggered = 0; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | line[0] = '\0'; | ||
| 362 | lp = 0; | ||
| 363 | return; | ||
| 58 | } | 364 | } |
| 59 | } | 365 | } |
| 60 | 366 | ||
| @@ -108,7 +414,7 @@ static int start_logging(void) | |||
| 108 | } | 414 | } |
| 109 | 415 | ||
| 110 | /* start capturing syslog */ | 416 | /* start capturing syslog */ |
| 111 | serr = syslog_relay_start_capture(syslog, syslog_callback, NULL); | 417 | serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL); |
| 112 | if (serr != SYSLOG_RELAY_E_SUCCESS) { | 418 | if (serr != SYSLOG_RELAY_E_SUCCESS) { |
| 113 | fprintf(stderr, "ERROR: Unable tot start capturing syslog.\n"); | 419 | fprintf(stderr, "ERROR: Unable tot start capturing syslog.\n"); |
| 114 | syslog_relay_client_free(syslog); | 420 | syslog_relay_client_free(syslog); |
| @@ -179,11 +485,25 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 179 | fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); | 485 | fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); |
| 180 | fprintf(is_error ? stderr : stdout, | 486 | fprintf(is_error ? stderr : stdout, |
| 181 | "Relay syslog of a connected device.\n\n" \ | 487 | "Relay syslog of a connected device.\n\n" \ |
| 488 | "OPTIONS:\n" \ | ||
| 182 | " -u, --udid UDID target specific device by UDID\n" \ | 489 | " -u, --udid UDID target specific device by UDID\n" \ |
| 183 | " -n, --network connect to network device even if available via USB\n" \ | 490 | " -n, --network connect to network device even if available via USB\n" \ |
| 491 | " -x, --exit exit when device disconnects\n" \ | ||
| 184 | " -h, --help prints usage information\n" \ | 492 | " -h, --help prints usage information\n" \ |
| 185 | " -d, --debug enable communication debugging\n" \ | 493 | " -d, --debug enable communication debugging\n" \ |
| 186 | " -x, --exit exit when device disconnects\n" \ | 494 | "\n" \ |
| 495 | "FILTER OPTIONS:\n" \ | ||
| 496 | " -m, --match STRING only print messages that contain STRING\n" \ | ||
| 497 | " -t, --trigger STRING start logging when matching STRING\n" \ | ||
| 498 | " -T, --untrigger STRING stop logging when matching STRING\n" \ | ||
| 499 | " -p, --process PROCESS only print messages from matching process(es)\n" \ | ||
| 500 | " -e, --exclude PROCESS print all messages except matching process(es)\n" \ | ||
| 501 | " PROCESS is a process name or multiple process names separated by \"|\".\n" \ | ||
| 502 | " -q, --quiet set a filter to exclude common noisy processes\n" \ | ||
| 503 | " --quiet-list prints the list of processes for --quiet and exits\n" \ | ||
| 504 | " -k, --kernel only print kernel messages\n" \ | ||
| 505 | " -K, --no-kernel suppress kernel messages\n" \ | ||
| 506 | "For filter example usage consult idevicesyslog(1) man page.\n" \ | ||
| 187 | "\n" \ | 507 | "\n" \ |
| 188 | "Homepage: <" PACKAGE_URL ">\n" | 508 | "Homepage: <" PACKAGE_URL ">\n" |
| 189 | ); | 509 | ); |
| @@ -191,6 +511,10 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 191 | 511 | ||
| 192 | int main(int argc, char *argv[]) | 512 | int main(int argc, char *argv[]) |
| 193 | { | 513 | { |
| 514 | int include_filter = 0; | ||
| 515 | int exclude_filter = 0; | ||
| 516 | int include_kernel = 0; | ||
| 517 | int exclude_kernel = 0; | ||
| 194 | int c = 0; | 518 | int c = 0; |
| 195 | const struct option longopts[] = { | 519 | const struct option longopts[] = { |
| 196 | { "debug", no_argument, NULL, 'd' }, | 520 | { "debug", no_argument, NULL, 'd' }, |
| @@ -198,6 +522,15 @@ int main(int argc, char *argv[]) | |||
| 198 | { "udid", required_argument, NULL, 'u' }, | 522 | { "udid", required_argument, NULL, 'u' }, |
| 199 | { "network", no_argument, NULL, 'n' }, | 523 | { "network", no_argument, NULL, 'n' }, |
| 200 | { "exit", no_argument, NULL, 'x' }, | 524 | { "exit", no_argument, NULL, 'x' }, |
| 525 | { "trigger", required_argument, NULL, 't' }, | ||
| 526 | { "untrigger", required_argument, NULL, 'T' }, | ||
| 527 | { "match", required_argument, NULL, 'm' }, | ||
| 528 | { "process", required_argument, NULL, 'p' }, | ||
| 529 | { "exclude", required_argument, NULL, 'e' }, | ||
| 530 | { "quiet", no_argument, NULL, 'q' }, | ||
| 531 | { "kernel", no_argument, NULL, 'k' }, | ||
| 532 | { "no-kernel", no_argument, NULL, 'K' }, | ||
| 533 | { "quiet-list", no_argument, NULL, 1 }, | ||
| 201 | { NULL, 0, NULL, 0} | 534 | { NULL, 0, NULL, 0} |
| 202 | }; | 535 | }; |
| 203 | 536 | ||
| @@ -208,7 +541,7 @@ int main(int argc, char *argv[]) | |||
| 208 | signal(SIGPIPE, SIG_IGN); | 541 | signal(SIGPIPE, SIG_IGN); |
| 209 | #endif | 542 | #endif |
| 210 | 543 | ||
| 211 | while ((c = getopt_long(argc, argv, "dhu:nx", longopts, NULL)) != -1) { | 544 | while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:e:p:qkK", longopts, NULL)) != -1) { |
| 212 | switch (c) { | 545 | switch (c) { |
| 213 | case 'd': | 546 | case 'd': |
| 214 | idevice_set_debug_level(1); | 547 | idevice_set_debug_level(1); |
| @@ -225,21 +558,143 @@ int main(int argc, char *argv[]) | |||
| 225 | case 'n': | 558 | case 'n': |
| 226 | lookup_opts |= IDEVICE_LOOKUP_PREFER_NETWORK; | 559 | lookup_opts |= IDEVICE_LOOKUP_PREFER_NETWORK; |
| 227 | break; | 560 | break; |
| 561 | case 'q': | ||
| 562 | exclude_filter++; | ||
| 563 | add_filter(QUIET_FILTER); | ||
| 564 | break; | ||
| 565 | case 'p': | ||
| 566 | case 'e': | ||
| 567 | if (c == 'p') { | ||
| 568 | include_filter++; | ||
| 569 | } else if (c == 'e') { | ||
| 570 | exclude_filter++; | ||
| 571 | } | ||
| 572 | if (!*optarg) { | ||
| 573 | fprintf(stderr, "ERROR: filter string must not be empty!\n"); | ||
| 574 | print_usage(argc, argv, 1); | ||
| 575 | return 2; | ||
| 576 | } | ||
| 577 | add_filter(optarg); | ||
| 578 | break; | ||
| 579 | case 'm': | ||
| 580 | if (!*optarg) { | ||
| 581 | fprintf(stderr, "ERROR: message filter string must not be empty!\n"); | ||
| 582 | print_usage(argc, argv, 1); | ||
| 583 | return 2; | ||
| 584 | } else { | ||
| 585 | char **new_msg_filters = realloc(msg_filters, sizeof(char*) * (num_msg_filters+1)); | ||
| 586 | if (!new_msg_filters) { | ||
| 587 | fprintf(stderr, "ERROR: realloc() failed\n"); | ||
| 588 | exit(EXIT_FAILURE); | ||
| 589 | } | ||
| 590 | msg_filters = new_msg_filters; | ||
| 591 | msg_filters[num_msg_filters] = strdup(optarg); | ||
| 592 | num_msg_filters++; | ||
| 593 | } | ||
| 594 | break; | ||
| 595 | case 't': | ||
| 596 | if (!*optarg) { | ||
| 597 | fprintf(stderr, "ERROR: trigger filter string must not be empty!\n"); | ||
| 598 | print_usage(argc, argv, 1); | ||
| 599 | return 2; | ||
| 600 | } else { | ||
| 601 | char **new_trigger_filters = realloc(trigger_filters, sizeof(char*) * (num_trigger_filters+1)); | ||
| 602 | if (!new_trigger_filters) { | ||
| 603 | fprintf(stderr, "ERROR: realloc() failed\n"); | ||
| 604 | exit(EXIT_FAILURE); | ||
| 605 | } | ||
| 606 | trigger_filters = new_trigger_filters; | ||
| 607 | trigger_filters[num_trigger_filters] = strdup(optarg); | ||
| 608 | num_trigger_filters++; | ||
| 609 | } | ||
| 610 | break; | ||
| 611 | case 'T': | ||
| 612 | if (!*optarg) { | ||
| 613 | fprintf(stderr, "ERROR: untrigger filter string must not be empty!\n"); | ||
| 614 | print_usage(argc, argv, 1); | ||
| 615 | return 2; | ||
| 616 | } else { | ||
| 617 | char **new_untrigger_filters = realloc(untrigger_filters, sizeof(char*) * (num_untrigger_filters+1)); | ||
| 618 | if (!new_untrigger_filters) { | ||
| 619 | fprintf(stderr, "ERROR: realloc() failed\n"); | ||
| 620 | exit(EXIT_FAILURE); | ||
| 621 | } | ||
| 622 | untrigger_filters = new_untrigger_filters; | ||
| 623 | untrigger_filters[num_untrigger_filters] = strdup(optarg); | ||
| 624 | num_untrigger_filters++; | ||
| 625 | } | ||
| 626 | break; | ||
| 627 | case 'k': | ||
| 628 | include_kernel++; | ||
| 629 | break; | ||
| 630 | case 'K': | ||
| 631 | exclude_kernel++; | ||
| 632 | break; | ||
| 228 | case 'x': | 633 | case 'x': |
| 229 | exit_on_disconnect = 1; | 634 | exit_on_disconnect = 1; |
| 230 | break; | 635 | break; |
| 231 | case 'h': | 636 | case 'h': |
| 232 | print_usage(argc, argv, 0); | 637 | print_usage(argc, argv, 0); |
| 233 | return 0; | 638 | return 0; |
| 639 | case 1: { | ||
| 640 | printf("%s\n", QUIET_FILTER); | ||
| 641 | return 0; | ||
| 642 | } | ||
| 234 | default: | 643 | default: |
| 235 | print_usage(argc, argv, 1); | 644 | print_usage(argc, argv, 1); |
| 236 | return 2; | 645 | return 2; |
| 237 | } | 646 | } |
| 238 | } | 647 | } |
| 239 | 648 | ||
| 649 | if (include_kernel > 0 && exclude_kernel > 0) { | ||
| 650 | fprintf(stderr, "ERROR: -k and -K cannot be used together.\n"); | ||
| 651 | print_usage(argc, argv, 1); | ||
| 652 | return 2; | ||
| 653 | } | ||
| 654 | |||
| 655 | if (include_filter > 0 && exclude_filter > 0) { | ||
| 656 | fprintf(stderr, "ERROR: -p and -e/-q cannot be used together.\n"); | ||
| 657 | print_usage(argc, argv, 1); | ||
| 658 | return 2; | ||
| 659 | } else if (include_filter > 0 && exclude_kernel > 0) { | ||
| 660 | fprintf(stderr, "ERROR: -p and -K cannot be used together.\n"); | ||
| 661 | print_usage(argc, argv, 1); | ||
| 662 | return 2; | ||
| 663 | } | ||
| 664 | |||
| 665 | if (exclude_filter > 0) { | ||
| 666 | proc_filter_excluding = 1; | ||
| 667 | if (include_kernel) { | ||
| 668 | int i = 0; | ||
| 669 | for (i = 0; i < num_proc_filters; i++) { | ||
| 670 | if (!strcmp(proc_filters[i], "kernel")) { | ||
| 671 | free(proc_filters[i]); | ||
| 672 | proc_filters[i] = NULL; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | } else if (exclude_kernel) { | ||
| 676 | add_filter("kernel"); | ||
| 677 | } | ||
| 678 | } else { | ||
| 679 | if (include_kernel) { | ||
| 680 | add_filter("kernel"); | ||
| 681 | } else if (exclude_kernel) { | ||
| 682 | proc_filter_excluding = 1; | ||
| 683 | add_filter("kernel"); | ||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | if (num_untrigger_filters > 0 && num_trigger_filters == 0) { | ||
| 688 | triggered = 1; | ||
| 689 | } | ||
| 690 | |||
| 240 | argc -= optind; | 691 | argc -= optind; |
| 241 | argv += optind; | 692 | argv += optind; |
| 242 | 693 | ||
| 694 | if (isatty(1)) { | ||
| 695 | use_colors = 1; | ||
| 696 | } | ||
| 697 | |||
| 243 | int num = 0; | 698 | int num = 0; |
| 244 | idevice_info_t *devices = NULL; | 699 | idevice_info_t *devices = NULL; |
| 245 | idevice_get_device_list_extended(&devices, &num); | 700 | idevice_get_device_list_extended(&devices, &num); |
| @@ -253,6 +708,9 @@ int main(int argc, char *argv[]) | |||
| 253 | } | 708 | } |
| 254 | } | 709 | } |
| 255 | 710 | ||
| 711 | line_buffer_size = 1024; | ||
| 712 | line = malloc(line_buffer_size); | ||
| 713 | |||
| 256 | idevice_event_subscribe(device_event_cb, NULL); | 714 | idevice_event_subscribe(device_event_cb, NULL); |
| 257 | 715 | ||
| 258 | while (!quit_flag) { | 716 | while (!quit_flag) { |
| @@ -261,6 +719,40 @@ int main(int argc, char *argv[]) | |||
| 261 | idevice_event_unsubscribe(); | 719 | idevice_event_unsubscribe(); |
| 262 | stop_logging(); | 720 | stop_logging(); |
| 263 | 721 | ||
| 722 | if (num_proc_filters > 0) { | ||
| 723 | int i; | ||
| 724 | for (i = 0; i < num_proc_filters; i++) { | ||
| 725 | free(proc_filters[i]); | ||
| 726 | } | ||
| 727 | free(proc_filters); | ||
| 728 | } | ||
| 729 | if (num_pid_filters > 0) { | ||
| 730 | free(pid_filters); | ||
| 731 | } | ||
| 732 | if (num_msg_filters > 0) { | ||
| 733 | int i; | ||
| 734 | for (i = 0; i < num_msg_filters; i++) { | ||
| 735 | free(msg_filters[i]); | ||
| 736 | } | ||
| 737 | free(msg_filters); | ||
| 738 | } | ||
| 739 | if (num_trigger_filters > 0) { | ||
| 740 | int i; | ||
| 741 | for (i = 0; i < num_trigger_filters; i++) { | ||
| 742 | free(trigger_filters[i]); | ||
| 743 | } | ||
| 744 | free(trigger_filters); | ||
| 745 | } | ||
| 746 | if (num_untrigger_filters > 0) { | ||
| 747 | int i; | ||
| 748 | for (i = 0; i < num_untrigger_filters; i++) { | ||
| 749 | free(untrigger_filters[i]); | ||
| 750 | } | ||
| 751 | free(untrigger_filters); | ||
| 752 | } | ||
| 753 | |||
| 754 | free(line); | ||
| 755 | |||
| 264 | free(udid); | 756 | free(udid); |
| 265 | 757 | ||
| 266 | return 0; | 758 | return 0; |
