+++ /dev/null
-/*
-**
-** 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.
-*/
-
-#define LOG_TAG "su"
-
-#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>
-
-#include <private/android_filesystem_config.h>
-
-
-void pwtoid(const char *tok, uid_t *uid, gid_t *gid)
-{
- struct passwd *pw;
- pw = getpwnam(tok);
- if (pw) {
- if (uid) *uid = pw->pw_uid;
- if (gid) *gid = pw->pw_gid;
- } else {
- uid_t tmpid = atoi(tok);
- if (uid) *uid = tmpid;
- if (gid) *gid = tmpid;
- }
-}
-
-void extract_uidgids(const char *uidgids, uid_t *uid, gid_t *gid, gid_t *gids,
- int *gids_count)
-{
- char *clobberablegids;
- char *nexttok;
- char *tok;
- int gids_found;
-
- if (!uidgids || !*uidgids) {
- *gid = *uid = 0;
- *gids_count = 0;
- return;
- }
- clobberablegids = strdup(uidgids);
- strcpy(clobberablegids, uidgids);
- nexttok = clobberablegids;
- tok = strsep(&nexttok, ",");
- pwtoid(tok, uid, gid);
- tok = strsep(&nexttok, ",");
- if (!tok) {
- /* gid is already set above */
- *gids_count = 0;
- free(clobberablegids);
- return;
- }
- pwtoid(tok, NULL, gid);
- gids_found = 0;
- while ((gids_found < *gids_count) && (tok = strsep(&nexttok, ","))) {
- pwtoid(tok, NULL, gids);
- gids_found++;
- gids++;
- }
- if (nexttok && gids_found == *gids_count) {
- fprintf(stderr, "too many group ids\n");
- }
- *gids_count = gids_found;
- free(clobberablegids);
-}
-
-/*
- * SU can be given a specific command to exec. UID _must_ be
- * specified for this (ie argc => 3).
- *
- * Usage:
- * su 1000
- * su 1000 ls -l
- * or
- * su [uid[,gid[,group1]...] [cmd]]
- * E.g.
- * su 1000,shell,net_bw_acct,net_bw_stats id
- * will return
- * uid=1000(system) gid=2000(shell) groups=3006(net_bw_stats),3007(net_bw_acct)
- */
-int main(int argc, char **argv)
-{
- struct passwd *pw;
- uid_t uid, myuid;
- gid_t gid, gids[10];
-
- /* Until we have something better, only root and the shell can use su. */
- myuid = getuid();
- if (myuid != AID_ROOT && myuid != AID_SHELL) {
- fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
- return 1;
- }
-
- if(argc < 2) {
- uid = gid = 0;
- } else {
- int gids_count = sizeof(gids)/sizeof(gids[0]);
- extract_uidgids(argv[1], &uid, &gid, gids, &gids_count);
- if(gids_count) {
- if(setgroups(gids_count, gids)) {
- fprintf(stderr, "su: failed to set groups\n");
- return 1;
- }
- }
- }
-
- 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) {
- int saved_errno = errno;
- fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2],
- strerror(errno));
- return -saved_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 (execvp(argv[2], exec_args) < 0) {
- int saved_errno = errno;
- fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2],
- strerror(errno));
- return -saved_errno;
- }
- }
-
- /* Default exec shell. */
- execlp("/system/bin/sh", "sh", NULL);
-
- fprintf(stderr, "su: exec failed\n");
- return 1;
-}