summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/idevicesyslog.134
-rw-r--r--tools/idevicesyslog.c174
2 files changed, 189 insertions, 19 deletions
diff --git a/docs/idevicesyslog.1 b/docs/idevicesyslog.1
index 0345bff..cb91193 100644
--- a/docs/idevicesyslog.1
+++ b/docs/idevicesyslog.1
@@ -42,17 +42,41 @@ Force writing colored output, e.g. when using \f[B]\-\-output\f[].
42.B \-\-syslog_relay 42.B \-\-syslog_relay
43Use old syslog_relay service instead of os_trace_relay (iOS 9+). 43Use old syslog_relay service instead of os_trace_relay (iOS 9+).
44 44
45.SH COMMANDS
46.TP
47.B pidlist
48Print a list with PID and name of all processes currently running on the device.
49.TP
50.B archive PATH
51Request a logarchive from the device. It will be written in tar format to PATH. To pipe to another process use \- as PATH.
52Below are some options to restrict the log message data.
53
54In order to view the logarchive in a compatible log viewer, you can pipe the output data to \f[B]tar\f[] and have it extract into a new directory:
55
56\f[B]mkdir test.logarchive && tools/idevicesyslog archive - |tar -C test.logarchive -xv\f[]
57
58This will also print the filenames while they are extracted.
59.TP
60Further options for \f[B]archive\f[]:
61.TP
62.B \-\-start\-time VALUE
63Start time of the log data as UNIX timestamp. Earlier messages will be dropped.
64.TP
65.B \-\-age\-limit VALUE
66Maximum age of the log data, supposedly number of days.
67.TP
68.B \-\-size\-limit VALUE
69Limit the size of the archive. The unit is currently unknown, so feel free to experiment.
70.TP
71Keep in mind that the device usually only has a backlog of a few minutes so the options might not have the desired effect. This is not a bug.
72
45.SH FILTER OPTIONS 73.SH FILTER OPTIONS
46.TP 74.TP
47.B \-m, \-\-match STRING 75.B \-m, \-\-match STRING
48only print messages that contain STRING 76only print messages that contain STRING
49
50.SH FILTER OPTIONS
51.TP 77.TP
52.B \-M, \-\-unmatch STRING 78.B \-M, \-\-unmatch STRING
53print messages that not contain STRING 79print messages that do not contain STRING
54
55This option will set a filter to only printed log messages that contain the given string.
56.TP 80.TP
57.B \-t, \-\-trigger STRING 81.B \-t, \-\-trigger STRING
58start logging when matching STRING 82start logging when matching STRING
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c
index bd73f88..8d7e33b 100644
--- a/tools/idevicesyslog.c
+++ b/tools/idevicesyslog.c
@@ -78,6 +78,10 @@ static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInte
78 78
79static int use_network = 0; 79static int use_network = 0;
80 80
81static long long start_time = -1;
82static long long size_limit = -1;
83static long long age_limit = -1;
84
81static char *line = NULL; 85static char *line = NULL;
82static int line_buffer_size = 0; 86static int line_buffer_size = 0;
83static int lp = 0; 87static int lp = 0;
@@ -538,7 +542,7 @@ static void ostrace_syslog_callback(const void* buf, size_t len, void* user_data
538 } 542 }
539} 543}
540 544
541static int start_logging(void) 545static int connect_service(int ostrace_required)
542{ 546{
543 idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); 547 idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
544 if (ret != IDEVICE_E_SUCCESS) { 548 if (ret != IDEVICE_E_SUCCESS) {
@@ -562,6 +566,13 @@ static int start_logging(void)
562 service_name = SYSLOG_RELAY_SERVICE_NAME; 566 service_name = SYSLOG_RELAY_SERVICE_NAME;
563 use_ostrace = 0; 567 use_ostrace = 0;
564 } 568 }
569 if (ostrace_required && !use_ostrace) {
570 fprintf(stderr, "ERROR: This operation requires iOS 9 or later.\n");
571 lockdownd_client_free(lockdown);
572 idevice_free(device);
573 device = NULL;
574 return -1;
575 }
565 576
566 /* start syslog_relay/os_trace_relay service */ 577 /* start syslog_relay/os_trace_relay service */
567 lerr = lockdownd_start_service(lockdown, service_name, &svc); 578 lerr = lockdownd_start_service(lockdown, service_name, &svc);
@@ -594,16 +605,6 @@ static int start_logging(void)
594 device = NULL; 605 device = NULL;
595 return -1; 606 return -1;
596 } 607 }
597
598 serr = ostrace_start_activity(ostrace, NULL, ostrace_syslog_callback, NULL);
599 if (serr != OSTRACE_E_SUCCESS) {
600 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
601 ostrace_client_free(ostrace);
602 ostrace = NULL;
603 idevice_free(device);
604 device = NULL;
605 return -1;
606 }
607 } else { 608 } else {
608 /* connect to syslog_relay service */ 609 /* connect to syslog_relay service */
609 syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR; 610 syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR;
@@ -615,9 +616,29 @@ static int start_logging(void)
615 device = NULL; 616 device = NULL;
616 return -1; 617 return -1;
617 } 618 }
619 }
620 return 0;
621}
618 622
619 /* start capturing syslog */ 623static int start_logging(void)
620 serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL); 624{
625 if (connect_service(0) < 0) {
626 return -1;
627 }
628
629 /* start capturing syslog */
630 if (ostrace) {
631 ostrace_error_t serr = ostrace_start_activity(ostrace, NULL, ostrace_syslog_callback, NULL);
632 if (serr != OSTRACE_E_SUCCESS) {
633 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
634 ostrace_client_free(ostrace);
635 ostrace = NULL;
636 idevice_free(device);
637 device = NULL;
638 return -1;
639 }
640 } else if (syslog) {
641 syslog_relay_error_t serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL);
621 if (serr != SYSLOG_RELAY_E_SUCCESS) { 642 if (serr != SYSLOG_RELAY_E_SUCCESS) {
622 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n"); 643 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
623 syslog_relay_client_free(syslog); 644 syslog_relay_client_free(syslog);
@@ -626,6 +647,8 @@ static int start_logging(void)
626 device = NULL; 647 device = NULL;
627 return -1; 648 return -1;
628 } 649 }
650 } else {
651 return -1;
629 } 652 }
630 653
631 fprintf(stdout, "[connected:%s]\n", udid); 654 fprintf(stdout, "[connected:%s]\n", udid);
@@ -654,6 +677,19 @@ static void stop_logging(void)
654 } 677 }
655} 678}
656 679
680static int write_callback(const void* buf, size_t len, void *user_data)
681{
682 FILE* f = (FILE*)user_data;
683 ssize_t res = fwrite(buf, 1, len, f);
684 if (res < 0) {
685 return -1;
686 }
687 if (quit_flag > 0) {
688 return -1;
689 }
690 return 0;
691}
692
657static void device_event_cb(const idevice_event_t* event, void* userdata) 693static void device_event_cb(const idevice_event_t* event, void* userdata)
658{ 694{
659 if (use_network && event->conn_type != CONNECTION_NETWORK) { 695 if (use_network && event->conn_type != CONNECTION_NETWORK) {
@@ -714,6 +750,15 @@ static void print_usage(int argc, char **argv, int is_error)
714 " --colors force writing colored output, e.g. for --output\n" 750 " --colors force writing colored output, e.g. for --output\n"
715 " --syslog_relay force use of syslog_relay service\n" 751 " --syslog_relay force use of syslog_relay service\n"
716 "\n" 752 "\n"
753 "COMMANDS:\n"
754 " pidlist Print pid and name of all running processes.\n"
755 " archive PATH Request a logarchive and write it to PATH.\n"
756 " Output can be piped to another process using - as PATH.\n"
757 " The file data will be in .tar format.\n"
758 " --start-time VALUE start time of the log data as UNIX timestamp\n"
759 " --age-limit VALUE maximum age of the log data\n"
760 " --size-limit VALUE limit the size of the archive\n"
761 "\n"
717 "FILTER OPTIONS:\n" 762 "FILTER OPTIONS:\n"
718 " -m, --match STRING only print messages that contain STRING\n" 763 " -m, --match STRING only print messages that contain STRING\n"
719 " -M, --unmatch STRING print messages that not contain STRING\n" 764 " -M, --unmatch STRING print messages that not contain STRING\n"
@@ -761,6 +806,9 @@ int main(int argc, char *argv[])
761 { "no-colors", no_argument, NULL, 2 }, 806 { "no-colors", no_argument, NULL, 2 },
762 { "colors", no_argument, NULL, 3 }, 807 { "colors", no_argument, NULL, 3 },
763 { "syslog_relay", no_argument, NULL, 4 }, 808 { "syslog_relay", no_argument, NULL, 4 },
809 { "start-time", required_argument, NULL, 5 },
810 { "size-limit", required_argument, NULL, 6 },
811 { "age-limit", required_argument, NULL, 7 },
764 { "output", required_argument, NULL, 'o' }, 812 { "output", required_argument, NULL, 'o' },
765 { "version", no_argument, NULL, 'v' }, 813 { "version", no_argument, NULL, 'v' },
766 { NULL, 0, NULL, 0} 814 { NULL, 0, NULL, 0}
@@ -897,6 +945,15 @@ int main(int argc, char *argv[])
897 case 4: 945 case 4:
898 force_syslog_relay = 1; 946 force_syslog_relay = 1;
899 break; 947 break;
948 case 5:
949 start_time = strtoll(optarg, NULL, 10);
950 break;
951 case 6:
952 size_limit = strtoll(optarg, NULL, 10);
953 break;
954 case 7:
955 age_limit = strtoll(optarg, NULL, 10);
956 break;
900 case 'o': 957 case 'o':
901 if (!*optarg) { 958 if (!*optarg) {
902 fprintf(stderr, "ERROR: --output option requires an argument!\n"); 959 fprintf(stderr, "ERROR: --output option requires an argument!\n");
@@ -969,6 +1026,95 @@ int main(int argc, char *argv[])
969 argc -= optind; 1026 argc -= optind;
970 argv += optind; 1027 argv += optind;
971 1028
1029 if (argc > 0) {
1030 if (!strcmp(argv[0], "pidlist")) {
1031 if (connect_service(1) < 0) {
1032 return 1;
1033 }
1034 plist_t list = NULL;
1035 ostrace_get_pid_list(ostrace, &list);
1036 ostrace_client_free(ostrace);
1037 ostrace = NULL;
1038 idevice_free(device);
1039 device = NULL;
1040 if (!list) {
1041 return 1;
1042 }
1043 plist_sort(list);
1044 plist_dict_iter iter = NULL;
1045 plist_dict_new_iter(list, &iter);
1046 if (iter) {
1047 plist_t node = NULL;
1048 do {
1049 char* key = NULL;
1050 node = NULL;
1051 plist_dict_next_item(list, iter, &key, &node);
1052 if (key) {
1053 printf("%s", key);
1054 free(key);
1055 if (PLIST_IS_DICT(node)) {
1056 plist_t pname = plist_dict_get_item(node, "ProcessName");
1057 if (PLIST_IS_STRING(pname)) {
1058 printf(" %s", plist_get_string_ptr(pname, NULL));
1059 }
1060 }
1061 printf("\n");
1062 }
1063 } while (node);
1064 plist_mem_free(iter);
1065 }
1066 plist_free(list);
1067 return 0;
1068 } else if (!strcmp(argv[0], "archive")) {
1069 if (force_syslog_relay) {
1070 force_syslog_relay = 0;
1071 }
1072 if (argc < 2) {
1073 fprintf(stderr, "Please specify an output filename.\n");
1074 return 1;
1075 }
1076 FILE* outf = NULL;
1077 if (!strcmp(argv[1], "-")) {
1078 if (isatty(1)) {
1079 fprintf(stderr, "Refusing to directly write to stdout. Pipe the output to another process.\n");
1080 return 1;
1081 }
1082 outf = stdout;
1083 } else {
1084 outf = fopen(argv[1], "w");
1085 }
1086 if (!outf) {
1087 fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
1088 return 1;
1089 }
1090 if (connect_service(1) < 0) {
1091 if (outf != stdout) {
1092 fclose(outf);
1093 }
1094 return 1;
1095 }
1096 plist_t options = plist_new_dict();
1097 if (start_time > 0) {
1098 plist_dict_set_item(options, "StartTime", plist_new_int(start_time));
1099 }
1100 if (size_limit > 0) {
1101 plist_dict_set_item(options, "SizeLimit", plist_new_int(size_limit));
1102 }
1103 if (age_limit > 0) {
1104 plist_dict_set_item(options, "AgeLimit", plist_new_int(age_limit));
1105 }
1106 ostrace_create_archive(ostrace, options, write_callback, outf);
1107 ostrace_client_free(ostrace);
1108 ostrace = NULL;
1109 idevice_free(device);
1110 device = NULL;
1111 if (outf != stdout) {
1112 fclose(outf);
1113 }
1114 return 0;
1115 }
1116 }
1117
972 int num = 0; 1118 int num = 0;
973 idevice_info_t *devices = NULL; 1119 idevice_info_t *devices = NULL;
974 idevice_get_device_list_extended(&devices, &num); 1120 idevice_get_device_list_extended(&devices, &num);
@@ -976,7 +1122,7 @@ int main(int argc, char *argv[])
976 if (num == 0) { 1122 if (num == 0) {
977 if (!udid) { 1123 if (!udid) {
978 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); 1124 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n");
979 return -1; 1125 return 1;
980 } 1126 }
981 1127
982 fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid); 1128 fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid);