summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/idevicesyslog.1104
-rw-r--r--tools/idevicesyslog.c506
2 files changed, 594 insertions, 16 deletions
diff --git a/docs/idevicesyslog.1 b/docs/idevicesyslog.1
index aa24339..fce1ff5 100644
--- a/docs/idevicesyslog.1
+++ b/docs/idevicesyslog.1
@@ -10,20 +10,106 @@ idevicesyslog \- Relay syslog of a connected device.
10Relay syslog of a connected device. 10Relay syslog of a connected device.
11 11
12.SH OPTIONS 12.SH OPTIONS
13.TP
14.B \-d, \-\-debug
15enable communication debugging.
16.TP 13.TP
17.B \-u, \-\-udid UDID 14.B \-u, \-\-udid UDID
18target specific device by UDID. 15target specific device by UDID
19.TP 16.TP
17.B \-n, \-\-network
18connect to network device even if available via USB
19.TP
20.B \-x, \-\-exit
21exit when device disconnects
22.TP
23.B \-d, \-\-debug
24enable communication debugging
25.TP
20.B \-h, \-\-help 26.B \-h, \-\-help
21prints usage information. 27prints usage information
28
29.SH FILTER OPTIONS
30.TP
31.B \-m, \-\-match STRING
32only print messages that contain STRING
33
34This option will set a filter to only printed log messages that contain the given string.
35.TP
36.B \-t, \-\-trigger STRING
37start logging when matching STRING
38
39When specified, logging will start as soon as a log messages is encountered that contains the given string. See also
40\f[B]\-T, \-\-untrigger\f[]. Other filters are still applied but obviously filtered messages are only printed after logging has started.
41.TP
42.B \-T, \-\-untrigger STRING
43stop logging when matching STRING
44
45When specified logging will halt as soon as a log message is encountered that contains the given string. See also
46\f[B]\-t, \-\-trigger\f[]. Other filters are still applied but obviously filtered messages are only printed before logging stops.
47
48NOTE: If no \f[B]\-\-trigger\f[] is given, idevicesyslog will exit after a matching log message was encountered.
49.TP
50.B \-p, \-\-process PROCESS
51only print messages from matching process(es)
52
53PROCESS is a string that can either be a numeric pid or a process name. It also supports multiple process names or pids in one string, separated by | (make sure to use quotes!).
54.TP
55.B \-e, \-\-exclude PROCESS
56print all messages except matching process(es)
57
58PROCESS is a string that can either be a numeric pid or a process name. It also supports multiple process names or pids in one string, separated by | (make sure to use quotes!).
59.TP
60.B \-q, \-\-quiet
61set a filter to exclude common noisy processes
62
63Since the syslog can be quite noisy, this quick command line switch allows to silence out a predefined set of commonly known processes. The list of processes that are silenced can be retrieved with \f[B]\-\-quiet\-list\f[].
64.TP
65.B \-\-quiet\-list
66prints the list of processes for \f[B]\-\-quiet\f[] and exits
67.TP
68.B \-k, \-\-kernel
69only print kernel messages
70
71This is actually equivalent to passing \f[B]\-\-process kernel\f[] with the exception that it can be used with \f[B]\-\-quiet\f[] to silence out the noisy process but still get all the kernel log messages.
72.TP
73.B \-K, \-\-no\-kernel
74suppress kernel messages
75
76This is equivalent to passing \f[B]\-\-exclude kernel\f[].
77
78.SH EXAMPLES
79.TP
80.B idevicesyslog \-u 00008030\-0000111ABC000DEF
81Relay syslog of device with UDID 00008030-0000111ABC000DEF.
82.TP
83.B idevicesyslog \-x
84Relay syslog of device and exit when the device is unplugged.
85.TP
86.B idevicesyslog \-m '####' \-e 'identityservicesd' \-K
87Only print log messages that contain the string #### and do NOT originate from identityservicesd or the kernel.
88.TP
89.B idevicesyslog \-p MyApp \-p ReportCrash
90Only print log messages from the process named 'MyApp' and 'ReportCrash'.
91.TP
92.B idevicesyslog \-p 'MyApp|ReportCrash'
93Same as previous example with different syntax.
94.TP
95.B idevicesyslog \-e 'backboardd|CommCenter|mDNSResponder'
96Suppress log messages from backboardd, CommCenter, and mDNSResponder.
97.TP
98.B idevicesyslog \-q \-k
99Suppress log messages from common noisy processes, but DO print kernel log messages.
100.TP
101.B idevicesyslog \-K
102Suppress log messages from kernel, but print everything else
103.TP
104.B idevicesyslog \-t 'backlight on' \-T 'backlight off' \-q
105Start logging when the device turns on backlight and stop logging when it turns backlight off, and suppress noisy processes
22 106
23.SH AUTHOR 107.SH AUTHORS
24Martin Szulecki 108Nikias Bassen, Martin Szulecki
25 109
26Man page written to conform with Debian by Julien Lavergne. 110Man page written to conform with Debian by Julien Lavergne.
27 111
28.SH ON THE WEB 112.SH ON THE WEB
29http://libimobiledevice.org 113https://github.com/libimobiledevice/libimobiledevice
114
115https://libimobiledevice.org
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
43static int quit_flag = 0; 43static int quit_flag = 0;
44static int exit_on_disconnect = 0; 44static int exit_on_disconnect = 0;
45static int use_colors = 0;
46static int show_device_name = 0;
45 47
46static char* udid = NULL; 48static char* udid = NULL;
49static char** proc_filters = NULL;
50static int num_proc_filters = 0;
51static int proc_filter_excluding = 0;
52
53static int* pid_filters = NULL;
54static int num_pid_filters = 0;
55
56static char** msg_filters = NULL;
57static int num_msg_filters = 0;
58
59static char** trigger_filters = NULL;
60static int num_trigger_filters = 0;
61static char** untrigger_filters = NULL;
62static int num_untrigger_filters = 0;
63static int triggered = 0;
47 64
48static idevice_t device = NULL; 65static idevice_t device = NULL;
49static syslog_relay_client_t syslog = NULL; 66static syslog_relay_client_t syslog = NULL;
50 67
68static 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
51enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK; 70enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK;
52 71
72static char *line = NULL;
73static int line_buffer_size = 0;
74static 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
97static 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
141static 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
149static void stop_logging(void);
150
53static void syslog_callback(char c, void *user_data) 151static 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
192int main(int argc, char *argv[]) 512int 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;