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
60 // Needed to supress extraneous "Loaded property_contexts from" message
selinux_log_callback_local(int type,const char * fmt,...)61 static int selinux_log_callback_local(int type, const char *fmt, ...)
62 {
63 va_list ap;
64
65 if (type == SELINUX_INFO) return 0;
66 va_start(ap, fmt);
67 verror_msg((char *)fmt, 0, ap);
68 va_end(ap);
69 return 0;
70 }
71
getprop_main(void)72 void getprop_main(void)
73 {
74 if (toys.optflags & FLAG_Z) {
75 union selinux_callback cb;
76
77 cb.func_log = selinux_log_callback_local;
78 selinux_set_callback(SELINUX_CB_LOG, cb);
79 TT.handle = selinux_android_prop_context_handle();
80 if (!TT.handle) error_exit("unable to get selinux property context handle");
81 }
82
83 if (*toys.optargs) {
84 if (toys.optflags & FLAG_Z) {
85 char *context = get_property_context(*toys.optargs);
86
87 puts(context);
88 if (CFG_TOYBOX_FREE) free(context);
89 } else {
90 if (__system_property_get(*toys.optargs, toybuf) <= 0)
91 strcpy(toybuf, toys.optargs[1] ? toys.optargs[1] : "");
92 puts(toybuf);
93 }
94 } else {
95 size_t i;
96
97 if (__system_property_foreach(add_property, NULL))
98 error_exit("property_list");
99 qsort(TT.nv, TT.size, 2*sizeof(char *), qstrcmp);
100 for (i = 0; i<TT.size; i++) printf("[%s]: [%s]\n", TT.nv[i*2],TT.nv[1+i*2]);
101 if (CFG_TOYBOX_FREE) {
102 for (i = 0; i<TT.size; i++) {
103 free(TT.nv[i*2]);
104 free(TT.nv[1+i*2]);
105 }
106 free(TT.nv);
107 }
108 }
109 if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_Z)) selabel_close(TT.handle);
110 }
111