diff options
Diffstat (limited to 'tools/idevicedebug.c')
-rw-r--r-- | tools/idevicedebug.c | 653 |
1 files changed, 365 insertions, 288 deletions
diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c index 74ce069..36c594e 100644 --- a/tools/idevicedebug.c +++ b/tools/idevicedebug.c @@ -32,6 +32,7 @@ #include <time.h> #include <unistd.h> #include <libgen.h> +#include <getopt.h> #ifdef WIN32 #include <windows.h> @@ -50,7 +51,8 @@ static int debug_level = 0; enum cmd_mode { CMD_NONE = 0, - CMD_RUN + CMD_RUN, + CMD_KILL }; static int quit_flag = 0; @@ -61,7 +63,12 @@ static void on_signal(int sig) quit_flag++; } -static instproxy_error_t instproxy_client_get_object_by_key_from_info_directionary_for_bundle_identifier(instproxy_client_t client, const char* appid, const char* key, plist_t* node) +static int cancel_receive() +{ + return quit_flag; +} + +static instproxy_error_t instproxy_client_get_object_by_key_from_info_dictionary_for_bundle_identifier(instproxy_client_t client, const char* appid, const char* key, plist_t* node) { if (!client || !appid || !key) return INSTPROXY_E_INVALID_ARG; @@ -108,103 +115,90 @@ static instproxy_error_t instproxy_client_get_object_by_key_from_info_directiona return INSTPROXY_E_SUCCESS; } -static debugserver_error_t debugserver_client_handle_response(debugserver_client_t client, char** response, int send_reply) +static debugserver_error_t debugserver_client_handle_response(debugserver_client_t client, char** response, int* exit_status) { debugserver_error_t dres = DEBUGSERVER_E_SUCCESS; - debugserver_command_t command = NULL; char* o = NULL; char* r = *response; + /* Documentation of response codes can be found here: + https://github.com/llvm/llvm-project/blob/4fe839ef3a51e0ea2e72ea2f8e209790489407a2/lldb/docs/lldb-gdb-remote.txt#L1269 + */ + if (r[0] == 'O') { /* stdout/stderr */ debugserver_decode_string(r + 1, strlen(r) - 1, &o); printf("%s", o); fflush(stdout); - if (o != NULL) { - free(o); - o = NULL; - } - - free(*response); - *response = NULL; - - if (!send_reply) - return dres; - - /* send reply */ - debugserver_command_new("OK", 0, NULL, &command); - dres = debugserver_client_send_command(client, command, response, NULL); - log_debug("result: %d", dres); - debugserver_command_free(command); - command = NULL; } else if (r[0] == 'T') { /* thread stopped information */ log_debug("Thread stopped. Details:\n%s", r + 1); - - free(*response); - *response = NULL; - - if (!send_reply) - return dres; - + if (exit_status != NULL) { + /* "Thread stopped" seems to happen when assert() fails. + Use bash convention where signals cause an exit + status of 128 + signal + */ + *exit_status = 128 + SIGABRT; + } + /* Break out of the loop. */ dres = DEBUGSERVER_E_UNKNOWN_ERROR; - } else if (r[0] == 'E' || r[0] == 'W') { - printf("%s: %s\n", (r[0] == 'E' ? "ERROR": "WARNING") , r + 1); - - free(*response); - *response = NULL; - - if (!send_reply) - return dres; - - /* send reply */ - debugserver_command_new("OK", 0, NULL, &command); - dres = debugserver_client_send_command(client, command, response, NULL); - log_debug("result: %d", dres); - debugserver_command_free(command); - command = NULL; + } else if (r[0] == 'E') { + printf("ERROR: %s\n", r + 1); + } else if (r[0] == 'W' || r[0] == 'X') { + /* process exited */ + debugserver_decode_string(r + 1, strlen(r) - 1, &o); + if (o != NULL) { + printf("Exit %s: %u\n", (r[0] == 'W' ? "status" : "due to signal"), o[0]); + if (exit_status != NULL) { + /* Use bash convention where signals cause an + exit status of 128 + signal + */ + *exit_status = o[0] + (r[0] == 'W' ? 0 : 128); + } + } else { + log_debug("Unable to decode exit status from %s", r); + dres = DEBUGSERVER_E_UNKNOWN_ERROR; + } } else if (r && strlen(r) == 0) { - if (!send_reply) - return dres; - - free(*response); - *response = NULL; - - /* no command */ - debugserver_command_new("OK", 0, NULL, &command); - dres = debugserver_client_send_command(client, command, response, NULL); - log_debug("result: %d", dres); - debugserver_command_free(command); - command = NULL; + log_debug("empty response"); } else { log_debug("ERROR: unhandled response '%s'", r); } + if (o != NULL) { + free(o); + o = NULL; + } + + free(*response); + *response = NULL; return dres; } -static void print_usage(int argc, char **argv) +static void print_usage(int argc, char **argv, int is_error) { - char *name = NULL; - name = strrchr(argv[0], '/'); - printf("Usage: %s [OPTIONS] COMMAND\n", (name ? name + 1: argv[0])); - printf("\n"); - printf("Interact with the debugserver service of a device.\n"); - printf("\n"); - printf("Where COMMAND is one of:\n"); - printf(" run BUNDLEID [ARGS...]\trun app with BUNDLEID and optional ARGS on device.\n"); - printf("\n"); - printf("The following OPTIONS are accepted:\n"); - printf(" -u, --udid UDID\ttarget specific device by UDID\n"); - printf(" -n, --network\t\tconnect to network device\n"); - printf(" --detach\t\tdetach from app after launch, keeping it running\n"); - printf(" -e, --env NAME=VALUE\tset environment variable NAME to VALUE\n"); - printf(" -d, --debug\t\tenable communication debugging\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf(" -v, --version\t\tprints version information\n"); - printf("\n"); - printf("Homepage: <" PACKAGE_URL ">\n"); - printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n"); + char *name = strrchr(argv[0], '/'); + fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] COMMAND\n", (name ? name + 1: argv[0])); + fprintf(is_error ? stderr : stdout, + "\n" + "Interact with the debugserver service of a device.\n" + "\n" + "Where COMMAND is one of:\n" + " run BUNDLEID [ARGS...] run app with BUNDLEID and optional ARGS on device.\n" + " kill BUNDLEID kill app with BUNDLEID\n" + "\n" + "The following OPTIONS are accepted:\n" + " -u, --udid UDID target specific device by UDID\n" + " -n, --network connect to network device\n" + " --detach detach from app after launch, keeping it running\n" + " -e, --env NAME=VALUE set environment variable NAME to VALUE\n" + " -d, --debug enable communication debugging\n" + " -h, --help prints usage information\n" + " -v, --version prints version information\n" + "\n" + "Homepage: <" PACKAGE_URL ">\n" + "Bug Reports: <" PACKAGE_BUGREPORT ">\n" + ); } int main(int argc, char *argv[]) @@ -230,6 +224,18 @@ int main(int argc, char *argv[]) debugserver_command_t command = NULL; debugserver_error_t dres = DEBUGSERVER_E_UNKNOWN_ERROR; + int c = 0; + const struct option longopts[] = { + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "udid", required_argument, NULL, 'u' }, + { "network", no_argument, NULL, 'n' }, + { "detach", no_argument, NULL, 1 }, + { "env", required_argument, NULL, 'e' }, + { "version", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } + }; + /* map signals */ signal(SIGINT, on_signal); signal(SIGTERM, on_signal); @@ -238,32 +244,33 @@ int main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); #endif - /* parse command line arguments */ - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { + while ((c = getopt_long(argc, argv, "dhu:ne:v", longopts, NULL)) != -1) { + switch (c) { + case 'd': debug_level++; - idevice_set_debug_level(debug_level); - continue; - } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { - i++; - if (!argv[i] || !*argv[i]) { - print_usage(argc, argv); - res = 0; - goto cleanup; + if (debug_level > 1) { + idevice_set_debug_level(debug_level-1); } - udid = argv[i]; - continue; - } else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--network")) { + break; + case 'u': + if (!*optarg) { + fprintf(stderr, "ERROR: UDID must not be empty!\n"); + print_usage(argc, argv, 1); + return 2; + } + udid = optarg; + break; + case 'n': use_network = 1; - continue; - } else if (!strcmp(argv[i], "--detach")) { + break; + case 1: detach_after_start = 1; - continue; - } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--env")) { - i++; - if (!argv[i] || (strlen(argv[i]) <= 1) || strchr(argv[i], '=') == NULL) { - print_usage(argc, argv); - res = 0; + break; + case 'e': + if (!*optarg || strchr(optarg, '=') == NULL) { + fprintf(stderr, "ERROR: environment variables need to be specified as -e KEY=VALUE\n"); + print_usage(argc, argv, 1); + res = 2; goto cleanup; } /* add environment variable */ @@ -271,50 +278,75 @@ int main(int argc, char *argv[]) newlist = malloc((environment_count + 1) * sizeof(char*)); else newlist = realloc(environment, (environment_count + 1) * sizeof(char*)); - newlist[environment_count++] = strdup(argv[i]); + newlist[environment_count++] = strdup(optarg); environment = newlist; - continue; - } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { - print_usage(argc, argv); + break; + case 'h': + print_usage(argc, argv, 0); res = 0; goto cleanup; - } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { + break; + case 'v': printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); res = 0; goto cleanup; - } else if (!strcmp(argv[i], "run")) { - cmd = CMD_RUN; - - i++; - if (!argv[i]) { - /* make sure at least the bundle identifier was provided */ - printf("Please supply the bundle identifier of the app to run.\n"); - print_usage(argc, argv); - res = 0; - goto cleanup; - } - /* read bundle identifier */ - bundle_identifier = argv[i]; break; - } else { - print_usage(argc, argv); - res = 0; + default: + print_usage(argc, argv, 1); + res = 2; goto cleanup; + break; } } + argc -= optind; + argv += optind; - if (environment) { - newlist = realloc(environment, (environment_count + 1) * sizeof(char*)); - newlist[environment_count] = NULL; - environment = newlist; + if (argc < 1) { + fprintf(stderr, "ERROR: Missing command.\n"); + print_usage(argc+optind, argv-optind, 1); + return 2; + } + + if (!strcmp(argv[0], "run")) { + cmd = CMD_RUN; + if (argc < 2) { + /* make sure at least the bundle identifier was provided */ + fprintf(stderr, "ERROR: Please supply the bundle identifier of the app to run.\n"); + print_usage(argc+optind, argv-optind, 1); + res = 2; + goto cleanup; + } + /* read bundle identifier */ + bundle_identifier = argv[1]; + i = 1; + } else if (!strcmp(argv[0], "kill")) { + cmd = CMD_KILL; + if (argc < 2) { + /* make sure at least the bundle identifier was provided */ + fprintf(stderr, "ERROR: Please supply the bundle identifier of the app to run.\n"); + print_usage(argc+optind, argv-optind, 1); + res = 2; + goto cleanup; + } + /* read bundle identifier */ + bundle_identifier = argv[1]; + i = 1; } /* verify options */ if (cmd == CMD_NONE) { - print_usage(argc, argv); + fprintf(stderr, "ERROR: Unsupported command specified.\n"); + print_usage(argc+optind, argv-optind, 1); + res = 2; goto cleanup; } + if (environment) { + newlist = realloc(environment, (environment_count + 1) * sizeof(char*)); + newlist[environment_count] = NULL; + environment = newlist; + } + /* connect to the device */ ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); if (ret != IDEVICE_E_SUCCESS) { @@ -326,198 +358,243 @@ int main(int argc, char *argv[]) goto cleanup; } - switch (cmd) { - case CMD_RUN: - default: - /* get the path to the app and it's working directory */ - if (instproxy_client_start_service(device, &instproxy_client, TOOL_NAME) != INSTPROXY_E_SUCCESS) { - fprintf(stderr, "Could not start installation proxy service.\n"); - goto cleanup; - } - plist_t container = NULL; - instproxy_client_get_object_by_key_from_info_directionary_for_bundle_identifier(instproxy_client, bundle_identifier, "Container", &container); - instproxy_client_get_path_for_bundle_identifier(instproxy_client, bundle_identifier, &path); - instproxy_client_free(instproxy_client); - instproxy_client = NULL; - - if (container && (plist_get_node_type(container) == PLIST_STRING)) { - plist_get_string_val(container, &working_directory); - log_debug("working_directory: %s\n", working_directory); - plist_free(container); - } else { - plist_free(container); - fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); - goto cleanup; - } + /* get the path to the app and it's working directory */ + if (instproxy_client_start_service(device, &instproxy_client, TOOL_NAME) != INSTPROXY_E_SUCCESS) { + fprintf(stderr, "Could not start installation proxy service.\n"); + goto cleanup; + } - /* start and connect to debugserver */ - if (debugserver_client_start_service(device, &debugserver_client, TOOL_NAME) != DEBUGSERVER_E_SUCCESS) { - fprintf(stderr, - "Could not start com.apple.debugserver!\n" - "Please make sure to mount the developer disk image first:\n" - " 1) Get the iOS version from `ideviceinfo -k ProductVersion`.\n" - " 2) Find the matching iPhoneOS DeveloperDiskImage.dmg files.\n" - " 3) Run `ideviceimagemounter` with the above path.\n"); - goto cleanup; - } + instproxy_client_get_path_for_bundle_identifier(instproxy_client, bundle_identifier, &path); + if (!path) { + fprintf(stderr, "Invalid bundle identifier: %s\n", bundle_identifier); + goto cleanup; + } - /* enable logging for the session in debug mode */ - if (debug_level) { - log_debug("Setting logging bitmask..."); - debugserver_command_new("QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE|LOG_RNB_PACKETS", 0, NULL, &command); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; - if (response) { - if (strncmp(response, "OK", 2)) { - debugserver_client_handle_response(debugserver_client, &response, 0); - goto cleanup; - } - free(response); - response = NULL; - } - } + plist_t container = NULL; + instproxy_client_get_object_by_key_from_info_dictionary_for_bundle_identifier(instproxy_client, bundle_identifier, "Container", &container); + instproxy_client_free(instproxy_client); + instproxy_client = NULL; - /* set maximum packet size */ - log_debug("Setting maximum packet size..."); - char* packet_size[2] = {strdup("1024"), NULL}; - debugserver_command_new("QSetMaxPacketSize:", 1, packet_size, &command); - free(packet_size[0]); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; - if (response) { - if (strncmp(response, "OK", 2)) { - debugserver_client_handle_response(debugserver_client, &response, 0); - goto cleanup; - } - free(response); - response = NULL; - } + if (container && (plist_get_node_type(container) == PLIST_STRING)) { + plist_get_string_val(container, &working_directory); + log_debug("working_directory: %s\n", working_directory); + plist_free(container); + } else { + plist_free(container); + fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); + goto cleanup; + } - /* set working directory */ - log_debug("Setting working directory..."); - char* working_dir[2] = {working_directory, NULL}; - debugserver_command_new("QSetWorkingDir:", 1, working_dir, &command); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; - if (response) { - if (strncmp(response, "OK", 2)) { - debugserver_client_handle_response(debugserver_client, &response, 0); - goto cleanup; - } - free(response); - response = NULL; - } + /* start and connect to debugserver */ + if (debugserver_client_start_service(device, &debugserver_client, TOOL_NAME) != DEBUGSERVER_E_SUCCESS) { + fprintf(stderr, + "Could not start com.apple.debugserver!\n" + "Please make sure to mount the developer disk image first:\n" + " 1) Get the iOS version from `ideviceinfo -k ProductVersion`.\n" + " 2) Find the matching iPhoneOS DeveloperDiskImage.dmg files.\n" + " 3) Run `ideviceimagemounter` with the above path.\n"); + goto cleanup; + } - /* set environment */ - if (environment) { - log_debug("Setting environment..."); - for (environment_index = 0; environment_index < environment_count; environment_index++) { - log_debug("setting environment variable: %s", environment[environment_index]); - debugserver_client_set_environment_hex_encoded(debugserver_client, environment[environment_index], NULL); - } - } + /* set receive params */ + if (debugserver_client_set_receive_params(debugserver_client, cancel_receive, 250) != DEBUGSERVER_E_SUCCESS) { + fprintf(stderr, "Error in debugserver_client_set_receive_params\n"); + goto cleanup; + } - /* set arguments and run app */ - log_debug("Setting argv..."); - i++; /* i is the offset of the bundle identifier, thus skip it */ - int app_argc = (argc - i + 2); - char **app_argv = (char**)malloc(sizeof(char*) * app_argc); - app_argv[0] = path; - log_debug("app_argv[%d] = %s", 0, app_argv[0]); - app_argc = 1; - while (i < argc && argv && argv[i]) { - log_debug("app_argv[%d] = %s", app_argc, argv[i]); - app_argv[app_argc++] = argv[i]; - i++; + /* enable logging for the session in debug mode */ + if (debug_level) { + log_debug("Setting logging bitmask..."); + debugserver_command_new("QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE|LOG_RNB_PACKETS;", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); + goto cleanup; } - app_argv[app_argc] = NULL; - debugserver_client_set_argv(debugserver_client, app_argc, app_argv, NULL); - free(app_argv); + free(response); + response = NULL; + } + } - /* check if launch succeeded */ - log_debug("Checking if launch succeeded..."); - debugserver_command_new("qLaunchSuccess", 0, NULL, &command); + /* set maximum packet size */ + log_debug("Setting maximum packet size..."); + char* packet_size[2] = { (char*)"1024", NULL}; + debugserver_command_new("QSetMaxPacketSize:", 1, packet_size, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); + goto cleanup; + } + free(response); + response = NULL; + } + + /* set working directory */ + log_debug("Setting working directory..."); + char* working_dir[2] = {working_directory, NULL}; + debugserver_command_new("QSetWorkingDir:", 1, working_dir, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); + goto cleanup; + } + free(response); + response = NULL; + } + + /* set environment */ + if (environment) { + log_debug("Setting environment..."); + for (environment_index = 0; environment_index < environment_count; environment_index++) { + log_debug("setting environment variable: %s", environment[environment_index]); + debugserver_client_set_environment_hex_encoded(debugserver_client, environment[environment_index], NULL); + } + } + + /* set arguments and run app */ + log_debug("Setting argv..."); + i++; /* i is the offset of the bundle identifier, thus skip it */ + int app_argc = (argc - i + 2); + char **app_argv = (char**)malloc(sizeof(char*) * app_argc); + app_argv[0] = path; + log_debug("app_argv[%d] = %s", 0, app_argv[0]); + app_argc = 1; + while (i < argc && argv && argv[i]) { + log_debug("app_argv[%d] = %s", app_argc, argv[i]); + app_argv[app_argc++] = argv[i]; + i++; + } + app_argv[app_argc] = NULL; + debugserver_client_set_argv(debugserver_client, app_argc, app_argv, NULL); + free(app_argv); + + /* check if launch succeeded */ + log_debug("Checking if launch succeeded..."); + debugserver_command_new("qLaunchSuccess", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); + goto cleanup; + } + free(response); + response = NULL; + } + + if (cmd == CMD_KILL) { + debugserver_command_new("k", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + goto cleanup; + } else + if (cmd == CMD_RUN) { + if (detach_after_start) { + log_debug("Detaching from app"); + debugserver_command_new("D", 0, NULL, &command); dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); debugserver_command_free(command); command = NULL; - if (response) { - if (strncmp(response, "OK", 2)) { - debugserver_client_handle_response(debugserver_client, &response, 0); - goto cleanup; - } - free(response); - response = NULL; + + res = (dres == DEBUGSERVER_E_SUCCESS) ? 0: -1; + goto cleanup; + } + + /* set thread */ + log_debug("Setting thread..."); + debugserver_command_new("Hc0", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); + goto cleanup; } + free(response); + response = NULL; + } - if (detach_after_start) { - log_debug("Detaching from app"); - debugserver_command_new("D", 0, NULL, &command); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; + /* continue running process */ + log_debug("Continue running process..."); + debugserver_command_new("c", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + log_debug("Continue response: %s", response); - res = (dres == DEBUGSERVER_E_SUCCESS) ? 0: -1; + /* main loop which is parsing/handling packets during the run */ + log_debug("Entering run loop..."); + while (!quit_flag) { + if (dres != DEBUGSERVER_E_SUCCESS) { + log_debug("failed to receive response; error %d", dres); break; } - /* set thread */ - log_debug("Setting thread..."); - debugserver_command_new("Hc0", 0, NULL, &command); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; if (response) { - if (strncmp(response, "OK", 2)) { - debugserver_client_handle_response(debugserver_client, &response, 0); - goto cleanup; + log_debug("response: %s", response); + if (strncmp(response, "OK", 2) != 0) { + dres = debugserver_client_handle_response(debugserver_client, &response, &res); + if (dres != DEBUGSERVER_E_SUCCESS) { + log_debug("failed to process response; error %d; %s", dres, response); + break; + } } - free(response); - response = NULL; + } + if (res >= 0) { + goto cleanup; } - /* continue running process */ - log_debug("Continue running process..."); - debugserver_command_new("c", 0, NULL, &command); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; - - /* main loop which is parsing/handling packets during the run */ - log_debug("Entering run loop..."); - while (!quit_flag) { - if (dres != DEBUGSERVER_E_SUCCESS) { - log_debug("failed to receive response"); - break; - } + dres = debugserver_client_receive_response(debugserver_client, &response, NULL); + } - if (response) { - log_debug("response: %s", response); - dres = debugserver_client_handle_response(debugserver_client, &response, 1); - } + /* ignore quit_flag after this point */ + if (debugserver_client_set_receive_params(debugserver_client, NULL, 5000) != DEBUGSERVER_E_SUCCESS) { + fprintf(stderr, "Error in debugserver_client_set_receive_params\n"); + goto cleanup; + } - sleep(1); + /* interrupt execution */ + debugserver_command_new("\x03", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); } + free(response); + response = NULL; + } - /* kill process after we finished */ - log_debug("Killing process..."); - debugserver_command_new("k", 0, NULL, &command); - dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); - debugserver_command_free(command); - command = NULL; - if (response) { - if (strncmp(response, "OK", 2)) { - debugserver_client_handle_response(debugserver_client, &response, 0); - goto cleanup; - } - free(response); - response = NULL; + /* kill process after we finished */ + log_debug("Killing process..."); + debugserver_command_new("k", 0, NULL, &command); + dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { + if (strncmp(response, "OK", 2) != 0) { + debugserver_client_handle_response(debugserver_client, &response, NULL); } + free(response); + response = NULL; + } + if (res < 0) { res = (dres == DEBUGSERVER_E_SUCCESS) ? 0: -1; - break; + } } cleanup: |