toolbox: add setprop, start, and stop
Move these from toybox as they're Android specific and more easily
maintained here.
A few changes during the conversion:
* Report error in setprop if value is not a UTF8 string; this would
previously fail only after attempting to set the property
* Inform users to check dmesg for further failure messages for all
three programs
* Only start/stop zygote_secondary if the device is not single arch
Bug: 117321744
Bug: 133901248
Test: setprop works, start and stop work on single and multi-arch.
Change-Id: Id2194cf2b65221bde38aff91f0e86b33edb37f42
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index ffda3a5..1926a4f 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -211,3 +211,32 @@
true truncate tty tunctl ulimit umount uname uniq unix2dos unlink
unshare uptime usleep uudecode uuencode uuidgen vconfig vmstat watch
wc which whoami xargs xxd yes zcat
+
+## Android R
+
+BSD: grep fsck\_msdos newfs\_msdos
+
+bzip2: bzcat bzip2 bunzip2
+
+one-true-awk: awk
+
+toolbox: getevent getprop setprop start stop
+
+toybox: acpi base64 basename bc blkid blockdev cal cat chattr chcon chgrp
+chmod chown chroot chrt cksum clear cmp comm cp cpio cut date dd df
+diff dirname dmesg dos2unix du echo egrep env expand expr fallocate
+false fgrep file find flock fmt free freeramdisk fsfreeze getconf
+getenforce getfattr grep groups gunzip gzip head help hostname hwclock
+i2cdetect i2cdump i2cget i2cset iconv id ifconfig inotifyd insmod
+install ionice iorenice iotop kill killall ln load\_policy log logname
+losetup ls lsattr lsmod lsof lspci lsusb makedevs md5sum microcom
+mkdir mkfifo mknod mkswap mktemp modinfo modprobe more mount mountpoint
+mv nbd-client nc netcat netstat nice nl nohup nproc nsenter od partprobe
+paste patch pgrep pidof ping ping6 pivot\_root pkill pmap printenv
+printf prlimit ps pwd pwdx readlink realpath renice restorecon rev
+rfkill rm rmdir rmmod runcon sed sendevent seq setenforce setfattr
+setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep sort split
+stat strings stty swapoff swapon sync sysctl tac tail tar taskset tee
+time timeout top touch tr traceroute traceroute6 true truncate tty tunctl
+ulimit umount uname uniq unix2dos unlink unshare uptime usleep uudecode
+uuencode uuidgen vconfig vmstat watch wc which whoami xargs xxd yes zcat
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 5289976..9ca5607 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -28,6 +28,8 @@
"toolbox.c",
"getevent.c",
"getprop.cpp",
+ "setprop.cpp",
+ "start.cpp",
],
generated_headers: [
"toolbox_input_labels",
@@ -40,6 +42,9 @@
symlinks: [
"getevent",
"getprop",
+ "setprop",
+ "start",
+ "stop",
],
}
diff --git a/toolbox/setprop.cpp b/toolbox/setprop.cpp
new file mode 100644
index 0000000..acf8c3e
--- /dev/null
+++ b/toolbox/setprop.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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 <ctype.h>
+#include <stdlib.h>
+#include <sys/system_properties.h>
+
+#include <iostream>
+
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+
+using android::base::SetProperty;
+using android::base::StartsWith;
+
+extern "C" int setprop_main(int argc, char** argv) {
+ if (argc != 3) {
+ std::cout << "usage: setprop NAME VALUE\n"
+ "\n"
+ "Sets an Android system property."
+ << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ auto name = std::string{argv[1]};
+ auto value = std::string{argv[2]};
+
+ // SetProperty() doesn't tell us why it failed, and actually can't recognize most failures, so
+ // we duplicate some of init's checks here to help the user.
+
+ if (name.front() == '.' || name.back() == '.') {
+ std::cerr << "Property names must not start or end with a '.'" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (name.find("..") != std::string::npos) {
+ std::cerr << "'..' is not allowed in a property name" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ for (const auto& c : name) {
+ if (!isalnum(c) && !strchr(":@_.-", c)) {
+ std::cerr << "Invalid character '" << c << "' in name '" << name << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (value.size() >= PROP_VALUE_MAX && !StartsWith(value, "ro.")) {
+ std::cerr << "Value '" << value << "' is too long, " << value.size()
+ << " bytes vs a max of " << PROP_VALUE_MAX << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
+ std::cerr << "Value '" << value << "' is not a UTF8 encoded string" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (!SetProperty(name, value)) {
+ std::cerr << "Failed to set property '" << name << "' to '" << value
+ << "'.\nSee dmesg for error reason." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/toolbox/start.cpp b/toolbox/start.cpp
new file mode 100644
index 0000000..b87ed15
--- /dev/null
+++ b/toolbox/start.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 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 <stdlib.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <android-base/properties.h>
+
+using android::base::GetProperty;
+using android::base::SetProperty;
+using namespace std::literals;
+
+static void ControlService(bool start, const std::string& service) {
+ if (!android::base::SetProperty(start ? "ctl.start" : "ctl.stop", service)) {
+ std::cerr << "Unable to " << (start ? "start" : "stop") << " service '" << service
+ << "'\nSee dmesg for error reason." << std::endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void ControlDefaultServices(bool start) {
+ std::vector<std::string> services = {"netd", "surfaceflinger", "zygote"};
+
+ // Only start zygote_secondary if not single arch.
+ std::string zygote_configuration = GetProperty("ro.zygote", "");
+ if (zygote_configuration != "zygote32" && zygote_configuration != "zygote64") {
+ services.emplace_back("zygote_secondary");
+ }
+
+ if (start) {
+ for (const auto& service : services) {
+ ControlService(true, service);
+ }
+ } else {
+ for (auto it = services.crbegin(); it != services.crend(); ++it) {
+ ControlService(false, *it);
+ }
+ }
+}
+
+static int StartStop(int argc, char** argv, bool start) {
+ if (getuid()) {
+ std::cerr << "Must be root" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 1) {
+ ControlDefaultServices(start);
+ }
+
+ if (argc == 2 && argv[1] == "--help"s) {
+ std::cout << "usage: " << (start ? "start" : "stop")
+ << " [SERVICE...]\n"
+ "\n"
+ << (start ? "Starts" : "Stops")
+ << " the given system service, or netd/surfaceflinger/zygotes." << std::endl;
+ return EXIT_SUCCESS;
+ }
+
+ for (int i = 1; i < argc; ++i) {
+ ControlService(start, argv[i]);
+ }
+ return EXIT_SUCCESS;
+}
+
+extern "C" int start_main(int argc, char** argv) {
+ return StartStop(argc, argv, true);
+}
+
+extern "C" int stop_main(int argc, char** argv) {
+ return StartStop(argc, argv, false);
+}
\ No newline at end of file
diff --git a/toolbox/tools.h b/toolbox/tools.h
index abeb3ef..9a7ebd2 100644
--- a/toolbox/tools.h
+++ b/toolbox/tools.h
@@ -1,3 +1,6 @@
TOOL(getevent)
TOOL(getprop)
+TOOL(setprop)
+TOOL(start)
+TOOL(stop)
TOOL(toolbox)