#include #include #include #include #include #include #include #include #include #include char g_flag; char G_flag; char n_flag; char r_flag; char u_flag; int print_groups(const struct passwd *pwd, const char *fmt, const int flag) { gid_t groups[NGROUPS_MAX]; int ngroups = NGROUPS_MAX; if (getgrouplist(pwd->pw_name, pwd->pw_gid, groups, &ngroups) < 0) return 1; for (int i = 0; i < ngroups; i++) { struct group *grp = getgrgid(groups[i]); if (grp && !n_flag) printf("%u", groups[i]); if ((!r_flag && n_flag) || flag) printf(fmt, grp->gr_name); if (g_flag && i == 0) break; putchar(' '); } return 0; } int ids(uid_t uid, struct passwd *pwd) { if (u_flag) { if (n_flag) printf("%s", pwd->pw_name); else printf("%u", uid); } else if (G_flag || g_flag) print_groups(pwd, "%s", 0); putchar('\n'); return 0; } int def_ids(uid_t uid, struct passwd *pwd) { printf("uid=%d(%s) gid=%d", uid, pwd->pw_name, pwd->pw_gid); struct group *grp = getgrgid(pwd->pw_gid); if (grp) printf("(%s)", grp->gr_name); printf(" groups="); print_groups(pwd, "(%s)", 1); putchar('\n'); return 0; } void usage(int sig) { puts("id [gGurn] [user]\n\t-u User ID\n\t-g Group ID\n\t-G Supplementary group IDs\n\t-n Print names instead of numbers\n\t-r Print real ID instead of effective ID"); exit(sig); } int main(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "gGnru")) != -1) { switch (opt) { case 'g': if (G_flag || u_flag) usage(1); g_flag = 1; break; case 'G': if (g_flag || u_flag) usage(1); G_flag = 1; break; case 'u': if (G_flag || g_flag) usage(1); u_flag = 1; break; case 'r': r_flag = 1; break; case 'n': n_flag = 1; break; default: usage(0); } } argv += optind; argc -= optind; uid_t uid = getuid(); struct passwd *pwd = getpwuid(uid); if (argv[0] != NULL) pwd = getpwnam(argv[0]); if (!pwd) { fprintf(stderr, "id: %s\n", strerror(errno)); return 1; } if (u_flag || G_flag || g_flag) return ids(uid, pwd); return def_ids(uid, pwd); }