aboutsummaryrefslogtreecommitdiff
path: root/toys/android/getprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/android/getprop.c')
-rw-r--r--toys/android/getprop.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/toys/android/getprop.c b/toys/android/getprop.c
new file mode 100644
index 00000000..51ef7f6b
--- /dev/null
+++ b/toys/android/getprop.c
@@ -0,0 +1,119 @@
+/* getprop.c - Get an Android system property
+ *
+ * Copyright 2015 The Android Open Source Project
+
+USE_GETPROP(NEWTOY(getprop, ">2Z", TOYFLAG_USR|TOYFLAG_SBIN))
+
+config GETPROP
+ bool "getprop"
+ default y
+ depends on TOYBOX_ON_ANDROID && TOYBOX_SELINUX
+ help
+ usage: getprop [NAME [DEFAULT]]
+
+ Gets an Android system property, or lists them all.
+*/
+
+#define FOR_getprop
+#include "toys.h"
+
+#include <sys/system_properties.h>
+
+#include <selinux/android.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
+
+GLOBALS(
+ size_t size;
+ char **nv; // name/value pairs: even=name, odd=value
+ struct selabel_handle *handle;
+)
+
+static char *get_property_context(const char *property)
+{
+ char *context = NULL;
+
+ if (selabel_lookup(TT.handle, &context, property, 1)) {
+ perror_exit("unable to lookup label for \"%s\"", property);
+ }
+ return context;
+}
+
+static void read_callback(void *unused, const char *name, const char *value,
+ unsigned serial)
+{
+ if (!(TT.size&31)) TT.nv = xrealloc(TT.nv, (TT.size+32)*2*sizeof(char *));
+
+ TT.nv[2*TT.size] = xstrdup((char *)name);
+ if (toys.optflags & FLAG_Z) {
+ TT.nv[1+2*TT.size++] = get_property_context(name);
+ } else {
+ TT.nv[1+2*TT.size++] = xstrdup((char *)value);
+ }
+}
+
+static void add_property(const prop_info *pi, void *unused)
+{
+ __system_property_read_callback(pi, read_callback, NULL);
+}
+
+static void print_callback(void *unused, const char *unused_name, const char *value,
+ unsigned unused_serial)
+{
+ puts(value);
+}
+
+// Needed to supress extraneous "Loaded property_contexts from" message
+static int selinux_log_callback_local(int type, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (type == SELINUX_INFO) return 0;
+ va_start(ap, fmt);
+ verror_msg((char *)fmt, 0, ap);
+ va_end(ap);
+ return 0;
+}
+
+void getprop_main(void)
+{
+ if (toys.optflags & FLAG_Z) {
+ union selinux_callback cb;
+
+ cb.func_log = selinux_log_callback_local;
+ selinux_set_callback(SELINUX_CB_LOG, cb);
+ TT.handle = selinux_android_prop_context_handle();
+ if (!TT.handle) error_exit("unable to get selinux property context handle");
+ }
+
+ if (*toys.optargs) {
+ if (toys.optflags & FLAG_Z) {
+ char *context = get_property_context(*toys.optargs);
+
+ puts(context);
+ if (CFG_TOYBOX_FREE) free(context);
+ } else {
+ const prop_info* pi = __system_property_find(*toys.optargs);
+ if (pi == NULL) {
+ puts(toys.optargs[1] ? toys.optargs[1] : "");
+ } else {
+ __system_property_read_callback(pi, print_callback, NULL);
+ }
+ }
+ } else {
+ size_t i;
+
+ if (__system_property_foreach(add_property, NULL))
+ error_exit("property_list");
+ qsort(TT.nv, TT.size, 2*sizeof(char *), qstrcmp);
+ for (i = 0; i<TT.size; i++) printf("[%s]: [%s]\n", TT.nv[i*2],TT.nv[1+i*2]);
+ if (CFG_TOYBOX_FREE) {
+ for (i = 0; i<TT.size; i++) {
+ free(TT.nv[i*2]);
+ free(TT.nv[1+i*2]);
+ }
+ free(TT.nv);
+ }
+ }
+ if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_Z)) selabel_close(TT.handle);
+}