diff options
Diffstat (limited to 'toys/android/getprop.c')
-rw-r--r-- | toys/android/getprop.c | 119 |
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); +} |