android_system_core/adb/daemon/abb.cpp
Elliott Hughes b4dc7be6c5 libbase: add ConsumePrefix/ConsumeSuffix.
adb was already using ConsumePrefix, and now we have another would-be
user in cutils. (There appears to be one place in adb that should use
ConsumeSuffix, so I'm assuming we'll want that sooner or later.)

I've kept these inline because adb and google3's versions both were, and
I'm easily led.

Test: treehugger
Change-Id: I29d99032f6f6ccbfaefece59725db8afb02a4c87
2019-05-03 12:49:31 -07:00

105 lines
3 KiB
C++

/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/wait.h>
#include <android-base/cmsg.h>
#include <android-base/strings.h>
#include <cmd.h>
#include "adb.h"
#include "adb_io.h"
#include "adb_utils.h"
#include "shell_service.h"
namespace {
class AdbFdTextOutput : public android::TextOutput {
public:
explicit AdbFdTextOutput(int fd) : mFD(fd) {}
private:
android::status_t print(const char* txt, size_t len) override {
return WriteFdExactly(mFD, txt, len) ? android::OK : -errno;
}
void moveIndent(int delta) override { /*not implemented*/
}
void pushBundle() override { /*not implemented*/
}
void popBundle() override { /*not implemented*/
}
private:
int mFD;
};
std::vector<std::string_view> parseCmdArgs(std::string_view args) {
std::vector<std::string_view> argv;
char delim = ABB_ARG_DELIMETER;
size_t size = args.size();
size_t base = 0;
while (base < size) {
size_t found;
for (found = base; found < size && args[found] && args[found] != delim; ++found)
;
if (found > base) {
argv.emplace_back(args.substr(base, found - base));
}
base = found + 1;
}
return argv;
}
} // namespace
static int execCmd(std::string_view args, int in, int out, int err) {
AdbFdTextOutput oin(out);
AdbFdTextOutput oerr(err);
return cmdMain(parseCmdArgs(args), oin, oerr, in, out, err, RunMode::kLibrary);
}
int main(int argc, char* const argv[]) {
signal(SIGPIPE, SIG_IGN);
int fd = STDIN_FILENO;
std::string data;
while (true) {
std::string error;
if (!ReadProtocolString(fd, &data, &error)) {
PLOG(ERROR) << "Failed to read message: " << error;
break;
}
std::string_view name = data;
auto protocol = SubprocessProtocol::kShell;
if (android::base::ConsumePrefix(&name, "abb:")) {
protocol = SubprocessProtocol::kShell;
} else if (android::base::ConsumePrefix(&name, "abb_exec:")) {
protocol = SubprocessProtocol::kNone;
} else {
LOG(FATAL) << "Unknown command prefix for abb: " << data;
}
unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol);
if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) {
PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data;
break;
}
}
}