![]() |
Linux
Application Development |
Michael K. Johnson Erik W. Troan |
/* id.c -- implements simple version of id command */
#include <grp.h>
#include <pwd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void usage(int die, char *error) {
fprintf(stderr, "Usage: id [<username>]\n");
if (error) fprintf(stderr, "%s\n", error);
if (die) exit(die);
}
void die(char *error) {
if (error) fprintf(stderr, "%s\n", error);
exit(3);
}
int main(int argc, char *argv[]) {
struct passwd *pw;
struct group *gp;
int current_user = 0;
uid_t id;
int i;
if (argc > 2)
usage(1, NULL);
if (argc == 1) {
id = getuid();
current_user = 1;
if (!(pw = getpwuid(id)))
usage(1, "Username does not exist");
} else {
if (!(pw = getpwnam(argv[1])))
usage(1, "Username does not exist");
id = pw->pw_uid;
}
printf("uid=%d(%s)", id, pw->pw_name);
if (gp = getgrgid(pw->pw_gid))
printf(" gid=%d(%s)", pw->pw_gid, gp->gr_name);
if (current_user) {
gid_t *gid_list;
int gid_size;
if (getuid() != geteuid()) {
id = geteuid();
if (!(pw = getpwuid(id)))
usage(1, "Username does not exist");
printf(" euid=%d(%s)", id, pw->pw_name);
}
if (getgid() != getegid()) {
id = getegid();
if (!(gp = getgrgid(id)))
usage(1, "Group does not exist");
printf(" egid=%d(%s)", id, gp->gr_name);
}
/* use getgroups interface to get current groups */
gid_size = getgroups(0, NULL);
if (gid_size) {
gid_list = malloc(gid_size * sizeof(gid_t));
getgroups(gid_size, gid_list);
for (i = 0; i < gid_size; i++) {
if (!(gp = getgrgid(gid_list[i])))
die("Group does not exist");
printf("%s%d(%s)", (i == 0) ? " groups=" : ",",
gp->gr_gid, gp->gr_name);
}
free(gid_list);
}
} else {
/* get list of groups from group database */
i = 0;
while (gp = getgrent()) {
char *c = *(gp->gr_mem);
while (c && *c) {
if (!strncmp(c, pw->pw_name, 16)) {
printf("%s%d(%s)", (i++ == 0) ? " groups=" : ",",
gp->gr_gid, gp->gr_name);
c = NULL;
} else {
c++;
}
}
}
endgrent();
}
printf("\n");
exit(0);
}