1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // This file contains classes and functionality to launch shell subprocesses 18 // in adbd and communicate between those subprocesses and the adb client. 19 // 20 // The main features exposed here are: 21 // 1. A ShellPacket class to wrap data in a simple protocol. Both adbd and 22 // the adb client use this class to transmit data between them. 23 // 2. Functions to launch a subprocess on the adbd side. 24 25 #ifndef SHELL_SERVICE_H_ 26 #define SHELL_SERVICE_H_ 27 28 #include <stdint.h> 29 30 #include <android-base/macros.h> 31 32 #include "adb.h" 33 34 // Class to send and receive shell protocol packets. 35 // 36 // To keep things simple and predictable, reads and writes block until an entire 37 // packet is complete. 38 // 39 // Example: read raw data from |fd| and send it in a packet. 40 // ShellProtocol* p = new ShellProtocol(protocol_fd); 41 // int len = adb_read(stdout_fd, p->data(), p->data_capacity()); 42 // packet->WritePacket(ShellProtocol::kIdStdout, len); 43 // 44 // Example: read a packet and print it to |stdout|. 45 // ShellProtocol* p = new ShellProtocol(protocol_fd); 46 // if (p->ReadPacket() && p->id() == kIdStdout) { 47 // fwrite(p->data(), 1, p->data_length(), stdout); 48 // } 49 class ShellProtocol { 50 public: 51 // This is an unscoped enum to make it easier to compare against raw bytes. 52 enum Id : uint8_t { 53 kIdStdin = 0, 54 kIdStdout = 1, 55 kIdStderr = 2, 56 kIdExit = 3, 57 58 // Close subprocess stdin if possible. 59 kIdCloseStdin = 4, 60 61 // Window size change (an ASCII version of struct winsize). 62 kIdWindowSizeChange = 5, 63 64 // Indicates an invalid or unknown packet. 65 kIdInvalid = 255, 66 }; 67 68 // ShellPackets will probably be too large to allocate on the stack so they 69 // should be dynamically allocated on the heap instead. 70 // 71 // |fd| is an open file descriptor to be used to send or receive packets. 72 explicit ShellProtocol(int fd); 73 virtual ~ShellProtocol(); 74 75 // Returns a pointer to the data buffer. data()76 const char* data() const { return buffer_ + kHeaderSize; } data()77 char* data() { return buffer_ + kHeaderSize; } 78 79 // Returns the total capacity of the data buffer. data_capacity()80 size_t data_capacity() const { return buffer_end_ - data(); } 81 82 // Reads a packet from the FD. 83 // 84 // If a packet is too big to fit in the buffer then Read() will split the 85 // packet across multiple calls. For example, reading a 50-byte packet into 86 // a 20-byte buffer would read 20 bytes, 20 bytes, then 10 bytes. 87 // 88 // Returns false if the FD closed or errored. 89 bool Read(); 90 91 // Returns the ID of the packet in the buffer. id()92 int id() const { return buffer_[0]; } 93 94 // Returns the number of bytes that have been read into the data buffer. data_length()95 size_t data_length() const { return data_length_; } 96 97 // Writes the packet currently in the buffer to the FD. 98 // 99 // Returns false if the FD closed or errored. 100 bool Write(Id id, size_t length); 101 102 private: 103 // Packets support 4-byte lengths. 104 typedef uint32_t length_t; 105 106 enum { 107 // It's OK if MAX_PAYLOAD doesn't match on the sending and receiving 108 // end, reading will split larger packets into multiple smaller ones. 109 kBufferSize = MAX_PAYLOAD, 110 111 // Header is 1 byte ID + 4 bytes length. 112 kHeaderSize = sizeof(Id) + sizeof(length_t) 113 }; 114 115 int fd_; 116 char buffer_[kBufferSize]; 117 size_t data_length_ = 0, bytes_left_ = 0; 118 119 // We need to be able to modify this value for testing purposes, but it 120 // will stay constant during actual program use. 121 char* buffer_end_ = buffer_ + sizeof(buffer_); 122 123 friend class ShellProtocolTest; 124 125 DISALLOW_COPY_AND_ASSIGN(ShellProtocol); 126 }; 127 128 #if !ADB_HOST 129 130 enum class SubprocessType { 131 kPty, 132 kRaw, 133 }; 134 135 enum class SubprocessProtocol { 136 kNone, 137 kShell, 138 }; 139 140 // Forks and starts a new shell subprocess. If |name| is empty an interactive 141 // shell is started, otherwise |name| is executed non-interactively. 142 // 143 // Returns an open FD connected to the subprocess or -1 on failure. 144 int StartSubprocess(const char* name, const char* terminal_type, 145 SubprocessType type, SubprocessProtocol protocol); 146 147 #endif // !ADB_HOST 148 149 #endif // SHELL_SERVICE_H_ 150