Loading adb/commandline.cpp +45 −26 Original line number Diff line number Diff line Loading @@ -467,6 +467,7 @@ struct StdinReadArgs { int stdin_fd, write_fd; bool raw_stdin; std::unique_ptr<ShellProtocol> protocol; char escape_char; }; // Loops to read from stdin and push the data to the given FD. Loading @@ -474,7 +475,6 @@ struct StdinReadArgs { // will take ownership of the object and delete it when finished. static void* stdin_read_thread_loop(void* x) { std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x)); int state = 0; #if !defined(_WIN32) // Mask SIGTTIN in case we're in a backgrounded process. Loading @@ -496,7 +496,7 @@ static void* stdin_read_thread_loop(void* x) { // Set up the initial window size. send_window_size_change(args->stdin_fd, args->protocol); char raw_buffer[1024]; char raw_buffer[BUFSIZ]; char* buffer_ptr = raw_buffer; size_t buffer_size = sizeof(raw_buffer); if (args->protocol != nullptr) { Loading @@ -504,6 +504,14 @@ static void* stdin_read_thread_loop(void* x) { buffer_size = args->protocol->data_capacity(); } // If we need to parse escape sequences, make life easy. if (args->raw_stdin && args->escape_char != '\0') { buffer_size = 1; } enum EscapeState { kMidFlow, kStartOfLine, kInEscape }; EscapeState state = kStartOfLine; while (true) { // Use unix_read() rather than adb_read() for stdin. D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd); Loading @@ -529,36 +537,36 @@ static void* stdin_read_thread_loop(void* x) { } break; } // If we made stdin raw, check input for the "~." escape sequence. In // If we made stdin raw, check input for escape sequences. In // this situation signals like Ctrl+C are sent remotely rather than // interpreted locally so this provides an emergency out if the remote // process starts ignoring the signal. SSH also does this, see the // "escape characters" section on the ssh man page for more info. if (args->raw_stdin) { for (int n = 0; n < r; n++) { switch (buffer_ptr[n]) { case '\n': state = 1; break; case '\r': state = 1; break; case '~': if (state == 1) { state++; if (args->raw_stdin && args->escape_char != '\0') { char ch = buffer_ptr[0]; if (ch == args->escape_char) { if (state == kStartOfLine) { state = kInEscape; // Swallow the escape character. continue; } else { state = 0; state = kMidFlow; } break; case '.': if (state == 2) { fprintf(stderr,"\r\n* disconnect *\r\n"); } else { if (state == kInEscape) { if (ch == '.') { fprintf(stderr,"\r\n[ disconnected ]\r\n"); stdin_raw_restore(); exit(0); } else { // We swallowed an escape character that wasn't part of // a valid escape sequence; time to cough it up. buffer_ptr[0] = args->escape_char; buffer_ptr[1] = ch; ++r; } default: state = 0; } state = (ch == '\n' || ch == '\r') ? kStartOfLine : kMidFlow; } } if (args->protocol) { Loading Loading @@ -603,6 +611,7 @@ static std::string ShellServiceString(bool use_shell_protocol, // On success returns the remote exit code if |use_shell_protocol| is true, // 0 otherwise. On failure returns 1. static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, char escape_char, const std::string& command) { std::string service_string = ShellServiceString(use_shell_protocol, type_arg, command); Loading @@ -628,6 +637,7 @@ static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, args->stdin_fd = STDIN_FILENO; args->write_fd = fd; args->raw_stdin = raw_stdin; args->escape_char = escape_char; if (use_shell_protocol) { args->protocol.reset(new ShellProtocol(args->write_fd)); } Loading Loading @@ -689,8 +699,17 @@ static int adb_shell(int argc, const char** argv, --argc; ++argv; int t_arg_count = 0; char escape_char = '~'; while (argc) { if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) { if (!strcmp(argv[0], "-e")) { if (argc < 2 || !(strlen(argv[1]) == 1 || strcmp(argv[1], "none") == 0)) { fprintf(stderr, "error: -e requires a single-character argument or 'none'\n"); return 1; } escape_char = (strcmp(argv[1], "none") == 0) ? 0 : argv[1][0]; argc -= 2; argv += 2; } else if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) { if (!CanUseFeature(features, kFeatureShell2)) { fprintf(stderr, "error: target doesn't support PTY args -Tt\n"); return 1; Loading Loading @@ -746,7 +765,7 @@ static int adb_shell(int argc, const char** argv, command = android::base::Join(std::vector<const char*>(argv, argv + argc), ' '); } return RemoteShell(use_shell_protocol, shell_type_arg, command); return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command); } static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz, Loading Loading
adb/commandline.cpp +45 −26 Original line number Diff line number Diff line Loading @@ -467,6 +467,7 @@ struct StdinReadArgs { int stdin_fd, write_fd; bool raw_stdin; std::unique_ptr<ShellProtocol> protocol; char escape_char; }; // Loops to read from stdin and push the data to the given FD. Loading @@ -474,7 +475,6 @@ struct StdinReadArgs { // will take ownership of the object and delete it when finished. static void* stdin_read_thread_loop(void* x) { std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x)); int state = 0; #if !defined(_WIN32) // Mask SIGTTIN in case we're in a backgrounded process. Loading @@ -496,7 +496,7 @@ static void* stdin_read_thread_loop(void* x) { // Set up the initial window size. send_window_size_change(args->stdin_fd, args->protocol); char raw_buffer[1024]; char raw_buffer[BUFSIZ]; char* buffer_ptr = raw_buffer; size_t buffer_size = sizeof(raw_buffer); if (args->protocol != nullptr) { Loading @@ -504,6 +504,14 @@ static void* stdin_read_thread_loop(void* x) { buffer_size = args->protocol->data_capacity(); } // If we need to parse escape sequences, make life easy. if (args->raw_stdin && args->escape_char != '\0') { buffer_size = 1; } enum EscapeState { kMidFlow, kStartOfLine, kInEscape }; EscapeState state = kStartOfLine; while (true) { // Use unix_read() rather than adb_read() for stdin. D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd); Loading @@ -529,36 +537,36 @@ static void* stdin_read_thread_loop(void* x) { } break; } // If we made stdin raw, check input for the "~." escape sequence. In // If we made stdin raw, check input for escape sequences. In // this situation signals like Ctrl+C are sent remotely rather than // interpreted locally so this provides an emergency out if the remote // process starts ignoring the signal. SSH also does this, see the // "escape characters" section on the ssh man page for more info. if (args->raw_stdin) { for (int n = 0; n < r; n++) { switch (buffer_ptr[n]) { case '\n': state = 1; break; case '\r': state = 1; break; case '~': if (state == 1) { state++; if (args->raw_stdin && args->escape_char != '\0') { char ch = buffer_ptr[0]; if (ch == args->escape_char) { if (state == kStartOfLine) { state = kInEscape; // Swallow the escape character. continue; } else { state = 0; state = kMidFlow; } break; case '.': if (state == 2) { fprintf(stderr,"\r\n* disconnect *\r\n"); } else { if (state == kInEscape) { if (ch == '.') { fprintf(stderr,"\r\n[ disconnected ]\r\n"); stdin_raw_restore(); exit(0); } else { // We swallowed an escape character that wasn't part of // a valid escape sequence; time to cough it up. buffer_ptr[0] = args->escape_char; buffer_ptr[1] = ch; ++r; } default: state = 0; } state = (ch == '\n' || ch == '\r') ? kStartOfLine : kMidFlow; } } if (args->protocol) { Loading Loading @@ -603,6 +611,7 @@ static std::string ShellServiceString(bool use_shell_protocol, // On success returns the remote exit code if |use_shell_protocol| is true, // 0 otherwise. On failure returns 1. static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, char escape_char, const std::string& command) { std::string service_string = ShellServiceString(use_shell_protocol, type_arg, command); Loading @@ -628,6 +637,7 @@ static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, args->stdin_fd = STDIN_FILENO; args->write_fd = fd; args->raw_stdin = raw_stdin; args->escape_char = escape_char; if (use_shell_protocol) { args->protocol.reset(new ShellProtocol(args->write_fd)); } Loading Loading @@ -689,8 +699,17 @@ static int adb_shell(int argc, const char** argv, --argc; ++argv; int t_arg_count = 0; char escape_char = '~'; while (argc) { if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) { if (!strcmp(argv[0], "-e")) { if (argc < 2 || !(strlen(argv[1]) == 1 || strcmp(argv[1], "none") == 0)) { fprintf(stderr, "error: -e requires a single-character argument or 'none'\n"); return 1; } escape_char = (strcmp(argv[1], "none") == 0) ? 0 : argv[1][0]; argc -= 2; argv += 2; } else if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) { if (!CanUseFeature(features, kFeatureShell2)) { fprintf(stderr, "error: target doesn't support PTY args -Tt\n"); return 1; Loading Loading @@ -746,7 +765,7 @@ static int adb_shell(int argc, const char** argv, command = android::base::Join(std::vector<const char*>(argv, argv + argc), ' '); } return RemoteShell(use_shell_protocol, shell_type_arg, command); return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command); } static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz, Loading