#include #include #include #include #include #include static int print_id_objects(); static bool flag_print_uid = false; static bool flag_print_gid = false; static bool flag_print_name = false; static bool flag_print_gid_all = false; int main(int argc, char** argv) { static const char* valid_option_characters = "ugGn"; int opt; while ((opt = getopt(argc, argv, valid_option_characters)) != -1) { switch (opt) { case 'u': flag_print_uid = true; break; case 'g': flag_print_gid = true; break; case 'G': flag_print_gid_all = true; break; case 'n': flag_print_name = true; break; default: fprintf(stderr, "usage: id [-%s]\n", valid_option_characters); return 1; } } if (flag_print_uid + flag_print_gid + flag_print_gid_all > 1) { fprintf(stderr, "cannot print \"only\" of more than one choice\n"); return 1; } int status = print_id_objects(); return status; } bool print_uid_object(uid_t uid) { if (flag_print_name) { struct passwd* pw = getpwuid(uid); printf("%s", pw ? pw->pw_name : "n/a"); } else printf("%u", uid); return true; } bool print_gid_object(gid_t gid) { if (flag_print_name) { struct group* gr = getgrgid(gid); printf("%s", gr ? gr->gr_name : "n/a"); } else printf("%u", gid); return true; } bool print_gid_list() { int extra_gid_count = getgroups(0, nullptr); if (extra_gid_count) { auto* extra_gids = (gid_t*)alloca(extra_gid_count * sizeof(gid_t)); int rc = getgroups(extra_gid_count, extra_gids); if (rc < 0) { perror("\ngetgroups"); return false; } for (int g = 0; g < extra_gid_count; ++g) { auto* gr = getgrgid(extra_gids[g]); if (flag_print_name && gr) printf("%s", gr->gr_name); else printf("%u", extra_gids[g]); if (g != extra_gid_count - 1) printf(" "); } } return true; } bool print_full_id_list() { uid_t uid = getuid(); gid_t gid = getgid(); struct passwd* pw = getpwuid(uid); struct group* gr = getgrgid(gid); printf("uid=%u(%s), gid=%u(%s)", uid, pw ? pw->pw_name : "n/a", gid, gr ? gr->gr_name : "n/a"); int extra_gid_count = getgroups(0, nullptr); if (extra_gid_count) { auto* extra_gids = (gid_t*)alloca(extra_gid_count * sizeof(gid_t)); int rc = getgroups(extra_gid_count, extra_gids); if (rc < 0) { perror("\ngetgroups"); return false; } printf(", groups="); for (int g = 0; g < extra_gid_count; ++g) { auto* gr = getgrgid(extra_gids[g]); if (gr) printf("%u(%s)", extra_gids[g], gr->gr_name); else printf("%u", extra_gids[g]); if (g != extra_gid_count - 1) printf(","); } } return true; } int print_id_objects() { if (flag_print_uid) { if (!print_uid_object(getuid())) return 1; } else if (flag_print_gid) { if (!print_gid_object(getgid())) return 1; } else if (flag_print_gid_all) { if (!print_gid_list()) return 1; } else { if (!print_full_id_list()) return 1; } printf("\n"); return 0; }