toybox/toys/android/getprop.c
<<
>>
Prefs
   1/* getprop.c - Get an Android system property
   2 *
   3 * Copyright 2015 The Android Open Source Project
   4
   5USE_GETPROP(NEWTOY(getprop, ">2Z", TOYFLAG_USR|TOYFLAG_SBIN))
   6
   7config 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
  26GLOBALS(
  27  size_t size;
  28  char **nv; // name/value pairs: even=name, odd=value
  29  struct selabel_handle *handle;
  30)
  31
  32static 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
  42static 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
  55static void add_property(const prop_info *pi, void *unused)
  56{
  57  __system_property_read_callback(pi, read_callback, NULL);
  58}
  59
  60static 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
  67static 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
  78void 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