1 /* getprop.c - Get an Android system property 2 * 3 * Copyright 2015 The Android Open Source Project 4 5 USE_GETPROP(NEWTOY(getprop, ">2Z", TOYFLAG_USR|TOYFLAG_SBIN)) 6 7 config GETPROP 8 bool "getprop" 9 default y 10 depends on TOYBOX_ON_ANDROID && TOYBOX_SELINUX 11 help 12 usage: getprop [NAME [DEFAULT]] 13 14 Gets an Android system property, or lists them all. 15 */ 16 17 #define FOR_getprop 18 #include "toys.h" 19 20 #include <sys/system_properties.h> 21 22 #include <selinux/android.h> 23 #include <selinux/label.h> 24 #include <selinux/selinux.h> 25 26 GLOBALS( 27 size_t size; 28 char **nv; // name/value pairs: even=name, odd=value 29 struct selabel_handle *handle; 30 ) 31 32 static char *get_property_context(const char *property) 33 { 34 char *context = NULL; 35 36 if (selabel_lookup(TT.handle, &context, property, 1)) { 37 perror_exit("unable to lookup label for \"%s\"", property); 38 } 39 return context; 40 } 41 42 static void read_callback(void *unused, const char *name, const char *value, 43 unsigned serial) 44 { 45 if (!(TT.size&31)) TT.nv = xrealloc(TT.nv, (TT.size+32)*2*sizeof(char *)); 46 47 TT.nv[2*TT.size] = xstrdup((char *)name); 48 if (toys.optflags & FLAG_Z) { 49 TT.nv[1+2*TT.size++] = get_property_context(name); 50 } else { 51 TT.nv[1+2*TT.size++] = xstrdup((char *)value); 52 } 53 } 54 55 static void add_property(const prop_info *pi, void *unused) 56 { 57 __system_property_read_callback(pi, read_callback, NULL); 58 } 59 60 static void print_callback(void *unused, const char *unused_name, const char *value, 61 unsigned unused_serial) 62 { 63 puts(value); 64 } 65 66 // Needed to supress extraneous "Loaded property_contexts from" message 67 static int selinux_log_callback_local(int type, const char *fmt, ...) 68 { 69 va_list ap; 70 71 if (type == SELINUX_INFO) return 0; 72 va_start(ap, fmt); 73 verror_msg((char *)fmt, 0, ap); 74 va_end(ap); 75 return 0; 76 } 77 78 void getprop_main(void) 79 { 80 if (toys.optflags & FLAG_Z) { 81 union selinux_callback cb; 82 83 cb.func_log = selinux_log_callback_local; 84 selinux_set_callback(SELINUX_CB_LOG, cb); 85 TT.handle = selinux_android_prop_context_handle(); 86 if (!TT.handle) error_exit("unable to get selinux property context handle"); 87 } 88 89 if (*toys.optargs) { 90 if (toys.optflags & FLAG_Z) { 91 char *context = get_property_context(*toys.optargs); 92 93 puts(context); 94 if (CFG_TOYBOX_FREE) free(context); 95 } else { 96 const prop_info* pi = __system_property_find(*toys.optargs); 97 if (pi == NULL) { 98 puts(toys.optargs[1] ? toys.optargs[1] : ""); 99 } else { 100 __system_property_read_callback(pi, print_callback, NULL); 101 } 102 } 103 } else { 104 size_t i; 105 106 if (__system_property_foreach(add_property, NULL)) 107 error_exit("property_list"); 108 qsort(TT.nv, TT.size, 2*sizeof(char *), qstrcmp); 109 for (i = 0; i<TT.size; i++) printf("[%s]: [%s]\n", TT.nv[i*2],TT.nv[1+i*2]); 110 if (CFG_TOYBOX_FREE) { 111 for (i = 0; i<TT.size; i++) { 112 free(TT.nv[i*2]); 113 free(TT.nv[1+i*2]); 114 } 115 free(TT.nv); 116 } 117 } 118 if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_Z)) selabel_close(TT.handle); 119 } 120