1 /* 2 ** Copyright (c) 2004 Haiku 3 ** Permission is hereby granted, free of charge, to any person obtaining a copy 4 ** of this software and associated documentation files (the "Software"), to deal 5 ** in the Software without restriction, including without limitation the rights 6 ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 ** copies of the Software, and to permit persons to whom the Software is 8 ** furnished to do so, subject to the following conditions: 9 ** 10 ** The above copyright notice and this permission notice shall be included in all 11 ** copies or substantial portions of the Software. 12 ** 13 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 ** SOFTWARE. 20 */ 21 22 23 #include <sys/stat.h> 24 #include <errno.h> 25 #include <getopt.h> 26 #include <grp.h> 27 #include <pwd.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <unistd.h> 32 33 static void print_user_info(int userID, char *suffix); 34 static void print_group_info(int groupID, char *suffix); 35 static void print_group_list(int listID); 36 static void print_combined_info(void); 37 static void suggest_help(void); 38 static void usage(void); 39 static void version(void); 40 41 char *progName; 42 static int gFlag, glFlag, nFlag, rFlag, uFlag; 43 struct passwd *euidName; 44 struct passwd *ruidName; 45 struct group *egidName; 46 struct group *rgidName; 47 uid_t eUID; 48 uid_t rUID; 49 gid_t eGID; 50 gid_t rGID; 51 gid_t groupList; 52 char *suffix; 53 54 55 static void 56 print_user_info(int userID, char *suffix) { 57 struct stat statBuffer; 58 struct passwd *userIDName; 59 if ((userIDName = getpwuid(userID)) != NULL) { 60 if (nFlag) 61 fprintf(stdout, "%s%s", userIDName->pw_name, suffix); 62 else 63 fprintf(stdout, "%u%s", eUID, suffix); 64 } else 65 fprintf(stdout, "%-8d%s", statBuffer.st_uid, suffix); 66 } 67 68 69 static void 70 print_group_info(int groupID, char *suffix) { 71 struct stat statBuffer; 72 struct group *groupIDName; 73 if ((groupIDName = getgrgid(groupID)) != NULL) { 74 if (nFlag) 75 fprintf(stdout, "%s%s", groupIDName->gr_name, suffix); 76 else 77 fprintf(stdout, "%u%s", groupID, suffix); 78 } else 79 fprintf(stdout, " %-8d%s", statBuffer.st_gid, suffix); 80 } 81 82 static void 83 print_group_list(int groupID) { 84 int cnt, id, lastID, nGroups; 85 gid_t *groups; 86 long ngroups_max; 87 88 ngroups_max = sysconf(NGROUPS_MAX) + 1; 89 groups = (gid_t *)malloc(ngroups_max *sizeof(gid_t)); 90 91 nGroups = getgroups(ngroups_max, groups); 92 93 suffix = ""; 94 print_group_info(groupID, suffix); 95 for (lastID = -1, cnt = 0; cnt < ngroups_max; ++cnt) { 96 if (lastID == (id = groups[cnt])) 97 continue; 98 suffix = " "; 99 print_group_info(id, suffix); 100 lastID = id; 101 } 102 fprintf(stdout, "\n"); 103 } 104 105 106 static void 107 print_combined_info() { 108 if ( eUID != rUID ) { 109 suffix = ""; 110 rFlag = 1; 111 fprintf(stdout, "uid="); 112 print_user_info(rUID, suffix); 113 fprintf(stdout, "("); 114 nFlag = 1; 115 print_user_info(rUID, suffix); 116 fprintf(stdout, ") gid="); 117 rFlag = 1; nFlag = 0; 118 print_group_info(rGID, suffix); 119 fprintf(stdout, "("); 120 rFlag = 0; nFlag = 1; 121 print_group_info(eGID, suffix); 122 fprintf(stdout, ") euid="); 123 rFlag = 0; nFlag = 0; 124 print_user_info(eUID, suffix); 125 fprintf(stdout, "("); 126 rFlag = 0; nFlag = 1; 127 print_user_info(eUID, suffix); 128 fprintf(stdout, ")\n"); 129 } else { 130 suffix = ""; 131 rFlag = 1; 132 fprintf(stdout, "uid="); 133 print_user_info(rUID, suffix); 134 fprintf(stdout, "("); 135 nFlag = 1; 136 print_user_info(rUID, suffix); 137 fprintf(stdout, ") gid="); 138 rFlag = 1; nFlag = 0; 139 print_group_info(rGID, suffix); 140 fprintf(stdout, "("); 141 rFlag = 1; nFlag = 1; 142 print_group_info(rGID, suffix); 143 fprintf(stdout, ")\n"); 144 } 145 } 146 147 148 static void 149 suggest_help(void) 150 { 151 (void)fprintf(stdout, "Try `%s --help' for more information.\n", progName); 152 } 153 154 155 static void 156 usage(void) 157 { 158 fprintf(stdout, 159 "%s Haiku (https://www.haiku-os.org/) 160 161 Usage: %s [OPTION]... [USERNAME] 162 163 -g, --group print only the group ID 164 -G, --groups print only the supplementary groups 165 -n, --name print a name instead of a number, for -ugG 166 -r, --real print the real ID instead of effective ID, for -ugG 167 -u, --user print only the user ID 168 --help display this help and exit 169 --version output version information and exit 170 171 Print information for USERNAME, or the current user. 172 173 ", progName, progName ); 174 } 175 176 177 static void 178 version(void) 179 { 180 fprintf(stdout, "%s Haiku (https://www.haiku-os.org/)\n", progName); 181 } 182 183 184 int 185 main(int argc, char *argv[]) 186 { 187 int argOption; 188 int indexptr = 0; 189 char * const * optargv = argv; 190 191 struct option groupOption = { "group", no_argument, 0, 1 } ; 192 struct option groupsOption = { "groups", no_argument, 0, 2 } ; 193 struct option nameOption = { "name", no_argument, 0, 3 } ; 194 struct option realOption = { "real", no_argument, 0, 4 } ; 195 struct option userOption = { "user", no_argument, 0, 5 } ; 196 struct option helpOption = { "help", no_argument, 0, 6 } ; 197 struct option versionOption = { "version", no_argument, 0, 7 } ; 198 199 struct option options[] = { 200 groupOption, groupsOption, nameOption, realOption, userOption, helpOption, versionOption, {0} 201 }; 202 203 struct passwd *suppliedName; 204 205 gFlag = glFlag = nFlag = rFlag = uFlag = 0; 206 progName = argv[0]; // don't put this before or between structs! werrry bad things happen. ;) 207 208 while ((argOption = getopt_long(argc, optargv, "gGnru", options, &indexptr)) != -1) { 209 210 switch (argOption) { 211 case 'g': 212 gFlag = 1; 213 break; 214 case 'G': 215 glFlag = 1; 216 break; 217 case 'n': 218 nFlag = 1; 219 break; 220 case 'r': 221 rFlag = 1; 222 break; 223 case 'u': 224 uFlag = 1; 225 break; 226 default: 227 switch (options[indexptr].val) { 228 case 6: // help 229 usage(); 230 exit(0); 231 case 7: // version 232 version(); 233 exit(0); 234 default: 235 suggest_help(); 236 exit(0); 237 } 238 break; 239 } 240 } 241 242 if (argc - optind > 1) 243 usage(); 244 245 if (argc - optind == 1) { 246 suppliedName = getpwnam(argv[optind]); 247 248 if (suppliedName == NULL) { 249 fprintf(stderr, "%s: %s: No such user\n", progName, argv[optind]); 250 suggest_help(); 251 exit(1); 252 } 253 rUID = eUID = suppliedName->pw_uid; 254 rGID = eGID = suppliedName->pw_gid; 255 } else { 256 eUID = geteuid (); 257 rUID = getuid (); 258 eGID = getegid (); 259 rGID = getgid (); 260 261 euidName = getpwuid(eUID); 262 ruidName = getpwuid(rUID); 263 egidName = getgrgid(eGID); 264 rgidName = getgrgid(rGID); 265 } 266 267 if ( gFlag + glFlag + uFlag > 1 ) { 268 fprintf(stderr, "%s: cannot print only user and only group\n", progName); 269 suggest_help(); 270 exit(1); 271 } 272 273 if ( gFlag + glFlag + uFlag == 0 && (rFlag || nFlag)) { 274 fprintf(stderr, "%s: cannot print only names or real IDs in default format\n", progName); 275 suggest_help(); 276 exit(1); 277 } 278 279 if (gFlag) { 280 // group information 281 suffix = "\n"; 282 if (rFlag) 283 print_group_info(rUID, suffix); 284 else 285 print_group_info(eUID, suffix); 286 exit(0); 287 } 288 289 if (glFlag) { 290 // group list 291 if (rFlag) 292 print_group_list(rUID); 293 else 294 print_group_list(eUID); 295 exit(0); 296 } 297 298 if (uFlag) { 299 // user information 300 suffix = "\n"; 301 if (rFlag) 302 print_user_info(rUID, suffix); 303 else 304 print_user_info(eUID, suffix); 305 exit(0); 306 } 307 308 // no arguments? print combined info. 309 print_combined_info(); 310 311 return B_NO_ERROR; 312 } 313