322 lines
6.7 KiB
C
322 lines
6.7 KiB
C
/* $Id$ */
|
|
/* Copyright (c) 2004-2020 Pierre Pronchery <khorben@defora.org> */
|
|
/* This file is part of DeforaOS Unix utils */
|
|
/* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, version 3 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <pwd.h>
|
|
#include <grp.h>
|
|
|
|
/* constants */
|
|
#ifndef PROGNAME
|
|
# define PROGNAME "id"
|
|
#endif
|
|
|
|
|
|
/* id */
|
|
static int _id_error(char const * message, int ret);
|
|
static int _id_G(char const * user, int flagn);
|
|
static int _id_g(char const * user, int flagn, int flagr);
|
|
static int _id_u(char const * user, int flagn, int flagr);
|
|
static int _id_all(char const * user);
|
|
static gid_t * _id_getgroups(int * n);
|
|
|
|
static int _id(char const * user, int flag, int flagn, int flagr)
|
|
{
|
|
if(flag == 'G')
|
|
return _id_G(user, flagn);
|
|
if(flag == 'g')
|
|
return _id_g(user, flagn, flagr);
|
|
if(flag == 'u')
|
|
return _id_u(user, flagn, flagr);
|
|
return _id_all(user);
|
|
}
|
|
|
|
/* _id_error */
|
|
static int _id_error(char const * message, int ret)
|
|
{
|
|
fputs(PROGNAME ": ", stderr);
|
|
perror(message);
|
|
return ret;
|
|
}
|
|
|
|
/* _id_G */
|
|
static int _id_G(char const * user, int flagn)
|
|
{
|
|
gid_t * groups;
|
|
int n;
|
|
int i;
|
|
struct group * gr;
|
|
struct passwd * pw;
|
|
char * g;
|
|
char ** p;
|
|
|
|
if(user == NULL)
|
|
{
|
|
if((groups = _id_getgroups(&n)) == NULL && n < 0)
|
|
return 1;
|
|
for(i = 0; i < n; i++)
|
|
if(flagn != 0 && (gr = getgrgid(groups[i])) != NULL)
|
|
printf("%s%s", (i > 0) ? " " : "", gr->gr_name);
|
|
else
|
|
printf("%s%u", (i > 0) ? " " : "", groups[i]);
|
|
putchar('\n');
|
|
free(groups);
|
|
return 0;
|
|
}
|
|
if((pw = getpwnam(user)) == NULL)
|
|
return _id_error(user, 1);
|
|
if((gr = getgrgid(pw->pw_gid)) == NULL)
|
|
return _id_error("getgrgid", 1);
|
|
if(flagn == 0)
|
|
printf("%u", (unsigned)gr->gr_gid);
|
|
else
|
|
fputs(gr->gr_name, stdout);
|
|
if((g = strdup(gr->gr_name)) == NULL)
|
|
return _id_error(gr->gr_name, 1);
|
|
setgrent();
|
|
for(gr = getgrent(); gr != NULL; gr = getgrent())
|
|
for(p = gr->gr_mem; p != NULL && *p != NULL; p++)
|
|
{
|
|
if(strcmp(pw->pw_name, *p) != 0
|
|
|| strcmp(g, gr->gr_name) == 0)
|
|
continue;
|
|
if(flagn == 0)
|
|
printf(" %u", (unsigned)gr->gr_gid);
|
|
else
|
|
printf(" %s", gr->gr_name);
|
|
}
|
|
putchar('\n');
|
|
endgrent();
|
|
free(g);
|
|
return 0;
|
|
}
|
|
|
|
/* _id_g */
|
|
static int _id_g(char const * user, int flagn, int flagr)
|
|
{
|
|
struct group * gr;
|
|
|
|
if(user == NULL)
|
|
{
|
|
if(flagn == 0)
|
|
{
|
|
printf("%u\n", flagr ? (unsigned)getegid()
|
|
: (unsigned)getgid());
|
|
return 0;
|
|
}
|
|
if((gr = getgrgid(flagr ? getegid() : getgid())) == NULL)
|
|
return _id_error("getgrgid", 1);
|
|
printf("%s\n", gr->gr_name);
|
|
return 0;
|
|
}
|
|
if((gr = getgrnam(user)) == NULL)
|
|
return _id_error(user, 1);
|
|
if(flagn == 0)
|
|
printf("%u\n", (unsigned)gr->gr_gid);
|
|
else
|
|
printf("%s\n", gr->gr_name);
|
|
return 0;
|
|
}
|
|
|
|
/* _id_u */
|
|
static int _id_u(char const * user, int flagn, int flagr)
|
|
{
|
|
struct passwd * passwd;
|
|
|
|
if(user == NULL)
|
|
{
|
|
if(flagn == 0)
|
|
{
|
|
printf("%u\n", flagr ? geteuid() : getuid());
|
|
return 0;
|
|
}
|
|
if((passwd = getpwuid(flagr ? geteuid() : getuid())) == NULL)
|
|
return _id_error("getpwuid", 1);
|
|
printf("%s\n", passwd->pw_name);
|
|
return 0;
|
|
}
|
|
if((passwd = getpwnam(user)) == NULL)
|
|
return _id_error(user, 1);
|
|
if(flagn == 0)
|
|
printf("%u\n", passwd->pw_uid);
|
|
else
|
|
printf("%s\n", passwd->pw_name);
|
|
return 0;
|
|
}
|
|
|
|
/* _id_all */
|
|
static struct group * _print_gid(gid_t gid);
|
|
|
|
static int _id_all(char const * user)
|
|
{
|
|
struct passwd * pw;
|
|
struct group * gr;
|
|
char * u;
|
|
int n;
|
|
gid_t * groups;
|
|
int i;
|
|
|
|
if(user == NULL)
|
|
{
|
|
if((pw = getpwuid(getuid())) == NULL)
|
|
{
|
|
putchar('\n');
|
|
return _id_error("getpwuid", 1);
|
|
}
|
|
printf("uid=%u(%s) ", (unsigned)pw->pw_uid, pw->pw_name);
|
|
if((gr = _print_gid(pw->pw_gid)) == NULL)
|
|
return 1;
|
|
if((u = strdup(gr->gr_name)) == NULL)
|
|
{
|
|
putchar('\n');
|
|
return _id_error(gr->gr_name, 1);
|
|
}
|
|
if(geteuid() != getuid())
|
|
{
|
|
if((pw = getpwuid(geteuid())) == NULL)
|
|
{
|
|
putchar('\n');
|
|
free(u);
|
|
return _id_error("getpwuid", 1);
|
|
}
|
|
printf(" euid=%u(%s) e", (unsigned)pw->pw_uid,
|
|
pw->pw_name);
|
|
if(_print_gid(pw->pw_gid) == NULL)
|
|
{
|
|
free(u);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((pw = getpwnam(user)) == NULL)
|
|
return _id_error(user, 1);
|
|
printf("uid=%u(%s) ", (unsigned)pw->pw_uid, pw->pw_name);
|
|
if((gr = _print_gid(pw->pw_gid)) == NULL)
|
|
return 1;
|
|
if((u = strdup(gr->gr_name)) == NULL)
|
|
{
|
|
putchar('\n');
|
|
return _id_error(gr->gr_name, 1);
|
|
}
|
|
}
|
|
if((groups = _id_getgroups(&n)) == NULL && n < 0)
|
|
return 1;
|
|
printf("%s", " groups=");
|
|
for(i = 0; i < n; i++)
|
|
if((gr = getgrgid(groups[i])) == NULL)
|
|
printf("%s%u", (i == 0) ? "" : ",",
|
|
(unsigned)gr->gr_gid);
|
|
else
|
|
printf("%s%u(%s)", (i == 0) ? "" : ",",
|
|
(unsigned)gr->gr_gid, gr->gr_name);
|
|
putchar('\n');
|
|
free(groups);
|
|
free(u);
|
|
return 0;
|
|
}
|
|
|
|
/* _print_gid */
|
|
static struct group * _print_gid(gid_t gid)
|
|
{
|
|
struct group * gr;
|
|
|
|
if((gr = getgrgid(gid)) == NULL)
|
|
{
|
|
putchar('\n');
|
|
_id_error("getgrgid", 0);
|
|
}
|
|
else
|
|
printf("gid=%u(%s)", gr->gr_gid, gr->gr_name);
|
|
return gr;
|
|
}
|
|
|
|
static gid_t * _id_getgroups(int * n)
|
|
{
|
|
gid_t * groups;
|
|
|
|
if((*n = getgroups(0, NULL)) < 0)
|
|
{
|
|
_id_error("getgroups", 1);
|
|
return NULL;
|
|
}
|
|
if(*n == 0)
|
|
groups = NULL;
|
|
else if((groups = malloc(sizeof(*groups) * (*n))) == NULL)
|
|
{
|
|
_id_error("malloc", 1);
|
|
return NULL;
|
|
}
|
|
if((*n = getgroups(*n, groups)) < 0)
|
|
{
|
|
free(groups);
|
|
_id_error("getgroups", 1);
|
|
return NULL;
|
|
}
|
|
return groups;
|
|
}
|
|
|
|
|
|
/* usage */
|
|
static int _usage(void)
|
|
{
|
|
fputs("Usage: " PROGNAME " [-Ggu][-nr] [user]\n\
|
|
-G Output all different group IDs\n\
|
|
-g Output only the effective group ID\n\
|
|
-u Output only the effective user ID\n\
|
|
-n Output the name as a string\n\
|
|
-r Output the real ID instead of the effective ID\n", stderr);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* main */
|
|
int main(int argc, char * argv[])
|
|
{
|
|
int o;
|
|
int flag = 0;
|
|
int flagn = 0;
|
|
int flagr = 0;
|
|
|
|
while((o = getopt(argc, argv, "Ggunr")) != -1)
|
|
switch(o)
|
|
{
|
|
case 'G':
|
|
case 'g':
|
|
case 'u':
|
|
flag = o;
|
|
break;
|
|
case 'n':
|
|
flagn = 1;
|
|
break;
|
|
case 'r':
|
|
flagr = 1;
|
|
break;
|
|
default:
|
|
return _usage();
|
|
}
|
|
if(optind == argc)
|
|
return _id(NULL, flag, flagn, flagr) == 0 ? 0 : 2;
|
|
if(optind + 1 == argc)
|
|
return _id(argv[optind], flag, flagn, flagr) == 0 ? 0 : 2;
|
|
return _usage();
|
|
}
|