• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GLOBALS(size_t size;char ** nv;struct selabel_handle * handle;)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 
read_callback(void * unused,const char * name,const char * value,unsigned serial)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 
add_property(const prop_info * pi,void * unused)55 static void add_property(const prop_info *pi, void *unused)
56 {
57   __system_property_read_callback(pi, read_callback, NULL);
58 }
59 
print_callback(void * unused,const char * unused_name,const char * value,unsigned unused_serial)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
selinux_log_callback_local(int type,const char * fmt,...)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 
getprop_main(void)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