Home | History | Annotate | Download | only in android
      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