Skip to content
Snippets Groups Projects
runas.c 5.39 KiB
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 * vim:expandtab:shiftwidth=8:tabstop=8:
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <sys/wait.h>

#define DEBUG 0

#ifndef NGROUPS_MAX
#define NGROUPS_MAX 32
#endif

static const char usage[] =
"Usage: %s -u user_id [-g grp_id] [-G[gid0,gid1,...]] command\n"
"  -u user_id           switch to UID user_id\n"
"  -g grp_id            switch to GID grp_id\n"
"  -G[gid0,gid1,...]    set supplementary groups\n";

void Usage_and_abort(const char *name)
{
        fprintf(stderr, usage, name);
        exit(-1);
}

int main(int argc, char **argv)
{
        char **my_argv, *name = argv[0], *grp;
        int status, c, i;
        int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
        uid_t user_id = 0;
        gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };

        if (argc == 1) {
                fprintf(stderr, "No parameter count\n");
                Usage_and_abort(name);
        }

        // get UID and GID
        while ((c = getopt(argc, argv, "+u:g:hG::")) != -1) {
                switch (c) {
                case 'u':
                        if (!isdigit(optarg[0])) {
                                struct passwd *pw = getpwnam(optarg);
                                if (pw == NULL) {
                                        fprintf(stderr, "parameter '%s' bad\n",
                                                optarg);
                                        Usage_and_abort(name);
                                }
                                user_id = pw->pw_uid;
                        } else {
                                user_id = (uid_t)atoi(optarg);
                        }
                        uid_is_set = 1;
                        if (!gid_is_set)
                                grp_id = user_id;
                        break;

                case 'g':
                        if (!isdigit(optarg[0])) {
                                struct group *gr = getgrnam(optarg);
                                if (gr == NULL) {
                                        fprintf(stderr, "getgrname %s failed\n",