diff --git a/src/apps/bin/id.c b/src/apps/bin/id.c new file mode 100644 index 0000000000..222a727037 --- /dev/null +++ b/src/apps/bin/id.c @@ -0,0 +1,312 @@ +/* +** Copyright (c) 2004 OBOS +** 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 OBOS (http://www.openbeos.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 OBOS (http://www.openbeos.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; +}