/* ** Copyright (c) 2004 Haiku ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal ** in the Software without restriction, including without limitation the rights ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is ** furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in all ** copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ** SOFTWARE. */ #include #include #include #include #include #include #include #include #include static void print_user_info(int userID, char *suffix); static void print_group_info(int groupID, char *suffix); static void print_group_list(int listID); static void print_combined_info(void); static void suggest_help(void); static void usage(void); static void version(void); char *progName; static int gFlag, glFlag, nFlag, rFlag, uFlag; struct passwd *euidName; struct passwd *ruidName; struct group *egidName; struct group *rgidName; uid_t eUID; uid_t rUID; gid_t eGID; gid_t rGID; gid_t groupList; char *suffix; static void print_user_info(int userID, char *suffix) { struct stat statBuffer; struct passwd *userIDName; if ((userIDName = getpwuid(userID)) != NULL) { if (nFlag) fprintf(stdout, "%s%s", userIDName->pw_name, suffix); else fprintf(stdout, "%u%s", eUID, suffix); } else fprintf(stdout, "%-8d%s", statBuffer.st_uid, suffix); } static void print_group_info(int groupID, char *suffix) { struct stat statBuffer; struct group *groupIDName; if ((groupIDName = getgrgid(groupID)) != NULL) { if (nFlag) fprintf(stdout, "%s%s", groupIDName->gr_name, suffix); else fprintf(stdout, "%u%s", groupID, suffix); } else fprintf(stdout, " %-8d%s", statBuffer.st_gid, suffix); } static void print_group_list(int groupID) { int cnt, id, lastID, nGroups; gid_t *groups; long ngroups_max; ngroups_max = sysconf(NGROUPS_MAX) + 1; groups = (gid_t *)malloc(ngroups_max *sizeof(gid_t)); nGroups = getgroups(ngroups_max, groups); suffix = ""; print_group_info(groupID, suffix); for (lastID = -1, cnt = 0; cnt < ngroups_max; ++cnt) { if (lastID == (id = groups[cnt])) continue; suffix = " "; print_group_info(id, suffix); lastID = id; } fprintf(stdout, "\n"); } static void print_combined_info() { if ( eUID != rUID ) { suffix = ""; rFlag = 1; fprintf(stdout, "uid="); print_user_info(rUID, suffix); fprintf(stdout, "("); nFlag = 1; print_user_info(rUID, suffix); fprintf(stdout, ") gid="); rFlag = 1; nFlag = 0; print_group_info(rGID, suffix); fprintf(stdout, "("); rFlag = 0; nFlag = 1; print_group_info(eGID, suffix); fprintf(stdout, ") euid="); rFlag = 0; nFlag = 0; print_user_info(eUID, suffix); fprintf(stdout, "("); rFlag = 0; nFlag = 1; print_user_info(eUID, suffix); fprintf(stdout, ")\n"); } else { suffix = ""; rFlag = 1; fprintf(stdout, "uid="); print_user_info(rUID, suffix); fprintf(stdout, "("); nFlag = 1; print_user_info(rUID, suffix); fprintf(stdout, ") gid="); rFlag = 1; nFlag = 0; print_group_info(rGID, suffix); fprintf(stdout, "("); rFlag = 1; nFlag = 1; print_group_info(rGID, suffix); fprintf(stdout, ")\n"); } } static void suggest_help(void) { (void)fprintf(stdout, "Try `%s --help' for more information.\n", progName); } static void usage(void) { fprintf(stdout, "%s Haiku (https://www.haiku-os.org/) Usage: %s [OPTION]... [USERNAME] -g, --group print only the group ID -G, --groups print only the supplementary groups -n, --name print a name instead of a number, for -ugG -r, --real print the real ID instead of effective ID, for -ugG -u, --user print only the user ID --help display this help and exit --version output version information and exit Print information for USERNAME, or the current user. ", progName, progName ); } static void version(void) { fprintf(stdout, "%s Haiku (https://www.haiku-os.org/)\n", progName); } int main(int argc, char *argv[]) { int argOption; int indexptr = 0; char * const * optargv = argv; struct option groupOption = { "group", no_argument, 0, 1 } ; struct option groupsOption = { "groups", no_argument, 0, 2 } ; struct option nameOption = { "name", no_argument, 0, 3 } ; struct option realOption = { "real", no_argument, 0, 4 } ; struct option userOption = { "user", no_argument, 0, 5 } ; struct option helpOption = { "help", no_argument, 0, 6 } ; struct option versionOption = { "version", no_argument, 0, 7 } ; struct option options[] = { groupOption, groupsOption, nameOption, realOption, userOption, helpOption, versionOption, {0} }; struct passwd *suppliedName; gFlag = glFlag = nFlag = rFlag = uFlag = 0; progName = argv[0]; // don't put this before or between structs! werrry bad things happen. ;) while ((argOption = getopt_long(argc, optargv, "gGnru", options, &indexptr)) != -1) { switch (argOption) { case 'g': gFlag = 1; break; case 'G': glFlag = 1; break; case 'n': nFlag = 1; break; case 'r': rFlag = 1; break; case 'u': uFlag = 1; break; default: switch (options[indexptr].val) { case 6: // help usage(); exit(0); case 7: // version version(); exit(0); default: suggest_help(); exit(0); } break; } } if (argc - optind > 1) usage(); if (argc - optind == 1) { suppliedName = getpwnam(argv[optind]); if (suppliedName == NULL) { fprintf(stderr, "%s: %s: No such user\n", progName, argv[optind]); suggest_help(); exit(1); } rUID = eUID = suppliedName->pw_uid; rGID = eGID = suppliedName->pw_gid; } else { eUID = geteuid (); rUID = getuid (); eGID = getegid (); rGID = getgid (); euidName = getpwuid(eUID); ruidName = getpwuid(rUID); egidName = getgrgid(eGID); rgidName = getgrgid(rGID); } if ( gFlag + glFlag + uFlag > 1 ) { fprintf(stderr, "%s: cannot print only user and only group\n", progName); suggest_help(); exit(1); } if ( gFlag + glFlag + uFlag == 0 && (rFlag || nFlag)) { fprintf(stderr, "%s: cannot print only names or real IDs in default format\n", progName); suggest_help(); exit(1); } if (gFlag) { // group information suffix = "\n"; if (rFlag) print_group_info(rUID, suffix); else print_group_info(eUID, suffix); exit(0); } if (glFlag) { // group list if (rFlag) print_group_list(rUID); else print_group_list(eUID); exit(0); } if (uFlag) { // user information suffix = "\n"; if (rFlag) print_user_info(rUID, suffix); else print_user_info(eUID, suffix); exit(0); } // no arguments? print combined info. print_combined_info(); return B_NO_ERROR; }