| /* 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); |
| } |
| |
| // 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 { |
| if (__system_property_get(*toys.optargs, toybuf) <= 0) |
| strcpy(toybuf, toys.optargs[1] ? toys.optargs[1] : ""); |
| puts(toybuf); |
| } |
| } 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); |
| } |