Extend toolbox with SE Android support.

Add -Z option to ls and ps for displaying security contexts.
Modify id to display security context.
Add new SELinux commands: chcon, getenforce, getsebool, load_policy, restorecon, runcon, setenforce, setsebool.

Change-Id: Ia20941be4a6cd706fe392fed6e38a37d880ec5f1
diff --git a/toolbox/getsebool.c b/toolbox/getsebool.c
new file mode 100644
index 0000000..aab5200
--- /dev/null
+++ b/toolbox/getsebool.c
@@ -0,0 +1,104 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <errno.h>
+#include <string.h>
+#include <selinux/selinux.h>
+
+static void usage(const char *progname)
+{
+    fprintf(stderr, "usage:  %s -a or %s boolean...\n", progname, progname);
+    exit(1);
+}
+
+int getsebool_main(int argc, char **argv)
+{
+    int i, get_all = 0, rc = 0, active, pending, len = 0, opt;
+    char **names;
+
+    while ((opt = getopt(argc, argv, "a")) > 0) {
+        switch (opt) {
+        case 'a':
+            if (argc > 2)
+                usage(argv[0]);
+            if (is_selinux_enabled() <= 0) {
+                fprintf(stderr, "%s:  SELinux is disabled\n",
+                        argv[0]);
+                return 1;
+            }
+            errno = 0;
+            rc = security_get_boolean_names(&names, &len);
+            if (rc) {
+                fprintf(stderr,
+                        "%s:  Unable to get boolean names:  %s\n",
+                        argv[0], strerror(errno));
+                return 1;
+            }
+            if (!len) {
+                printf("No booleans\n");
+                return 0;
+            }
+            get_all = 1;
+            break;
+        default:
+            usage(argv[0]);
+        }
+    }
+
+    if (is_selinux_enabled() <= 0) {
+        fprintf(stderr, "%s:  SELinux is disabled\n", argv[0]);
+        return 1;
+    }
+    if (!len) {
+        if (argc < 2)
+            usage(argv[0]);
+        len = argc - 1;
+        names = malloc(sizeof(char *) * len);
+        if (!names) {
+            fprintf(stderr, "%s:  out of memory\n", argv[0]);
+            return 2;
+        }
+        for (i = 0; i < len; i++) {
+            names[i] = strdup(argv[i + 1]);
+            if (!names[i]) {
+                fprintf(stderr, "%s:  out of memory\n",
+                        argv[0]);
+                return 2;
+            }
+        }
+    }
+
+    for (i = 0; i < len; i++) {
+        active = security_get_boolean_active(names[i]);
+        if (active < 0) {
+            if (get_all && errno == EACCES)
+                continue;
+            fprintf(stderr, "Error getting active value for %s\n",
+                    names[i]);
+            rc = -1;
+            goto out;
+        }
+        pending = security_get_boolean_pending(names[i]);
+        if (pending < 0) {
+            fprintf(stderr, "Error getting pending value for %s\n",
+                    names[i]);
+            rc = -1;
+            goto out;
+        }
+        if (pending != active) {
+            printf("%s --> %s pending: %s\n", names[i],
+                   (active ? "on" : "off"),
+                   (pending ? "on" : "off"));
+        } else {
+            printf("%s --> %s\n", names[i],
+                   (active ? "on" : "off"));
+        }
+    }
+
+out:
+    for (i = 0; i < len; i++)
+        free(names[i]);
+    free(names);
+    return rc;
+}