OSDN Git Service

fixup multiuser mode detection and usage, add -u option to print multiuser mode
authorKoushik Dutta <koushd@gmail.com>
Mon, 25 Feb 2013 05:37:07 +0000 (21:37 -0800)
committerKoushik Dutta <koushd@gmail.com>
Mon, 25 Feb 2013 05:37:07 +0000 (21:37 -0800)
Superuser/jni/su/activity.c
Superuser/jni/su/su.c
Superuser/jni/su/su.h
Superuser/libs/android-support-v4.jar [new file with mode: 0644]

index 48c30cd..9d6619c 100644 (file)
@@ -73,10 +73,8 @@ static int silent_run(char* command) {
 
 int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
     int needs_owner_login_prompt = 0;
-    if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) {
-        snprintf(user, user_len, "");
-    }
-    else if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER) {
+    
+    if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
         if (0 != ctx->user.android_user_id) {
             needs_owner_login_prompt = 1;
         }
@@ -85,9 +83,11 @@ int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len)
     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
         snprintf(user, user_len, "--user %d", ctx->user.android_user_id);
     }
+    else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
+        snprintf(user, user_len, "");
+    }
     else {
-        // unknown mode?
-        return -1;
+        snprintf(user, user_len, "--user 0");
     }
     
     return needs_owner_login_prompt;
@@ -96,14 +96,13 @@ int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len)
 int send_result(struct su_context *ctx, policy_t policy) {
     char user[64];
     int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
-    if (needs_owner_login_prompt == -1)
-        return -1;
 
     char result_command[ARG_MAX];
-    snprintf(result_command, sizeof(result_command), "exec /system/bin/am " ACTION_RESULT " --es from_name '%s' --es desired_name '%s' --ei uid %d --ei desired_uid %d --es command '%s' --es action %s %s",
+    snprintf(result_command, sizeof(result_command), "exec /system/bin/am " ACTION_RESULT " --ei binary_version %d --es from_name '%s' --es desired_name '%s' --ei uid %d --ei desired_uid %d --es command '%s' --es action %s %s",
+        VERSION_CODE,
         ctx->from.name, ctx->to.name,
         ctx->from.uid, ctx->to.uid, get_command(&ctx->to), policy == ALLOW ? "allow" : "deny", user);
-    LOGD(result_command);
+    // LOGD(result_command);
     return silent_run(result_command);
 }
 
@@ -114,9 +113,6 @@ int send_request(struct su_context *ctx) {
     // so there will be two activities shown.
     char user[64];
     int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
-    if (needs_owner_login_prompt == -1)
-        return -1;
-
 
     int ret;
     if (needs_owner_login_prompt) {
index 74f6b8e..4fece12 100644 (file)
@@ -159,19 +159,42 @@ static int from_init(struct su_initiator *from) {
     return 0;
 }
 
-static void read_options(struct su_context *ctx) {
+static int get_multiuser_mode() {
+    char *data;
+    char sdk_ver[PROPERTY_VALUE_MAX];
+
+    data = read_file("/system/build.prop");
+    get_property(data, sdk_ver, "ro.build.version.sdk", "0");
+    free(data);
+
+    int sdk = atoi(sdk_ver);
+    if (sdk < 16)
+        return MULTIUSER_MODE_NONE;
+
+    int ret = MULTIUSER_MODE_OWNER_ONLY;
     char mode[12];
     FILE *fp;
     if ((fp = fopen(REQUESTOR_MULTIUSER_MODE, "r"))) {
+        int last = strlen(mode) - 1;
+        if (mode[last] == '\n')
+            mode[last] = '\0';
         fgets(mode, sizeof(mode), fp);
         LOGD("multiuser mode: %s", mode);
-        if (strcmp(mode, "user\n") == 0) {
-            ctx->user.multiuser_mode = MULTIUSER_MODE_USER;
-        } else if (strcmp(mode, "owner\n") == 0) {
-            ctx->user.multiuser_mode = MULTIUSER_MODE_OWNER;
+        if (strcmp(mode, MULTIUSER_VALUE_USER) == 0) {
+            ret = MULTIUSER_MODE_USER;
+        } else if (strcmp(mode, MULTIUSER_VALUE_OWNER_MANAGED) == 0) {
+            ret = MULTIUSER_MODE_OWNER_MANAGED;
+        }
+        else {
+            ret = MULTIUSER_MODE_OWNER_ONLY;
         }
         fclose(fp);
     }
+    return ret;
+}
+
+static void read_options(struct su_context *ctx) {
+    ctx->user.multiuser_mode = get_multiuser_mode();
 }
 
 static void user_init(struct su_context *ctx) {
@@ -388,6 +411,7 @@ static void usage(int status) {
     "  -m, -p,\n"
     "  --preserve-environment        do not change environment variables\n"
     "  -s, --shell SHELL             use SHELL instead of the default " DEFAULT_SHELL "\n"
+    "  -u                            display the multiuser mode and exit\n"
     "  -v, --version                 display version number and exit\n"
     "  -V                            display version code and exit,\n"
     "                                this is used almost exclusively by Superuser.apk\n");
@@ -602,7 +626,7 @@ int main(int argc, char *argv[]) {
         { NULL, 0, NULL, 0 },
     };
 
-    while ((c = getopt_long(argc, argv, "+c:hlmps:Vv", long_opts, NULL)) != -1) {
+    while ((c = getopt_long(argc, argv, "+c:hlmps:Vvu", long_opts, NULL)) != -1) {
         switch(c) {
         case 'c':
             ctx.to.command = optarg;
@@ -626,6 +650,22 @@ int main(int argc, char *argv[]) {
         case 'v':
             printf("%s\n", VERSION);
             exit(EXIT_SUCCESS);
+        case 'u':
+            switch (get_multiuser_mode()) {
+            case MULTIUSER_MODE_USER:
+                printf("%s\n", MULTIUSER_VALUE_USER);
+                break;
+            case MULTIUSER_MODE_OWNER_MANAGED:
+                printf("%s\n", MULTIUSER_VALUE_OWNER_MANAGED);
+                break;
+            case MULTIUSER_MODE_OWNER_ONLY:
+                printf("%s\n", MULTIUSER_VALUE_OWNER_ONLY);
+                break;
+            case MULTIUSER_MODE_NONE:
+                printf("%s\n", MULTIUSER_VALUE_NONE);
+                break;
+            }
+            exit(EXIT_SUCCESS);
         default:
             /* Bionic getopt_long doesn't terminate its error output by newline */
             fprintf(stderr, "\n");
index a2a5fc9..48a0c21 100644 (file)
@@ -115,11 +115,17 @@ typedef enum {
   // only owner can su
   MULTIUSER_MODE_OWNER_ONLY = 0,
   // owner gets a su prompt
-  MULTIUSER_MODE_OWNER = 1,
+  MULTIUSER_MODE_OWNER_MANAGED = 1,
   // user gets a su prompt
   MULTIUSER_MODE_USER = 2,
+  MULTIUSER_MODE_NONE = 3,
 } multiuser_mode_t;
 
+#define MULTIUSER_VALUE_OWNER_ONLY    "owner"
+#define MULTIUSER_VALUE_OWNER_MANAGED "managed"
+#define MULTIUSER_VALUE_USER          "user"
+#define MULTIUSER_VALUE_NONE          "none"
+
 typedef enum {
     INTERACTIVE = 0,
     DENY = 1,
diff --git a/Superuser/libs/android-support-v4.jar b/Superuser/libs/android-support-v4.jar
new file mode 100644 (file)
index 0000000..6080877
Binary files /dev/null and b/Superuser/libs/android-support-v4.jar differ