summaryrefslogtreecommitdiff
path: root/su/su.c
diff options
context:
space:
mode:
Diffstat (limited to 'su/su.c')
-rw-r--r--su/su.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/su/su.c b/su/su.c
new file mode 100644
index 00000000..aac981ea
--- /dev/null
+++ b/su/su.c
@@ -0,0 +1,86 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <time.h>
+
+#include <pwd.h>
+
+/*
+ * SU can be given a specific command to exec. UID _must_ be
+ * specified for this (ie argc => 3). Full path of file must be specified.
+ *
+ * Usage:
+ * su 1000
+ * su 1000 /system/bin/ls -l
+ */
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+ int uid, gid;
+
+ if(argc < 2) {
+ uid = gid = 0;
+ } else {
+ pw = getpwnam(argv[1]);
+
+ if(pw == 0) {
+ uid = gid = atoi(argv[1]);
+ } else {
+ uid = pw->pw_uid;
+ gid = pw->pw_gid;
+ }
+ }
+
+ if(setgid(gid) || setuid(uid)) {
+ fprintf(stderr,"su: permission denied\n");
+ return 1;
+ }
+
+ /* User specified command for exec. */
+ if (argc == 3 ) {
+ if (execlp(argv[2], argv[2], NULL) < 0) {
+ fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2],
+ strerror(errno));
+ return -errno;
+ }
+ } else if (argc > 3) {
+ /* Copy the rest of the args from main. */
+ char *exec_args[argc - 1];
+ memset(exec_args, 0, sizeof(exec_args));
+ memcpy(exec_args, &argv[2], sizeof(exec_args));
+ if (execv(argv[2], exec_args) < 0) {
+ fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2],
+ strerror(errno));
+ return -errno;
+ }
+ }
+
+ /* Default exec shell. */
+ execlp("/system/bin/sh", "sh", NULL);
+
+ fprintf(stderr, "su: exec failed\n");
+ return 1;
+}
+