Serenity Operating System
at portability 180 lines 5.4 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <LibCore/ArgsParser.h> 28#include <alloca.h> 29#include <grp.h> 30#include <pwd.h> 31#include <stdio.h> 32#include <unistd.h> 33 34static int print_id_objects(); 35 36static bool flag_print_uid = false; 37static bool flag_print_gid = false; 38static bool flag_print_name = false; 39static bool flag_print_gid_all = false; 40 41int main(int argc, char** argv) 42{ 43 if (unveil("/etc/passwd", "r") < 0) { 44 perror("unveil"); 45 return 1; 46 } 47 48 if (unveil("/etc/group", "r") < 0) { 49 perror("unveil"); 50 return 1; 51 } 52 53 if (unveil(nullptr, nullptr) < 0) { 54 perror("unveil"); 55 return 1; 56 } 57 58 if (pledge("stdio rpath", nullptr) < 0) { 59 perror("pledge"); 60 return 1; 61 } 62 63 Core::ArgsParser args_parser; 64 args_parser.add_option(flag_print_uid, "Print UID", nullptr, 'u'); 65 args_parser.add_option(flag_print_gid, "Print GID", nullptr, 'g'); 66 args_parser.add_option(flag_print_gid_all, "Print all GIDs", nullptr, 'G'); 67 args_parser.add_option(flag_print_name, "Print name", nullptr, 'n'); 68 args_parser.parse(argc, argv); 69 70 if (flag_print_name && !(flag_print_uid || flag_print_gid || flag_print_gid_all)) { 71 fprintf(stderr, "cannot print only names or real IDs in default format\n"); 72 return 1; 73 } 74 75 if (flag_print_uid + flag_print_gid + flag_print_gid_all > 1) { 76 fprintf(stderr, "cannot print \"only\" of more than one choice\n"); 77 return 1; 78 } 79 80 int status = print_id_objects(); 81 return status; 82} 83 84bool print_uid_object(uid_t uid) 85{ 86 if (flag_print_name) { 87 struct passwd* pw = getpwuid(uid); 88 printf("%s", pw ? pw->pw_name : "n/a"); 89 } else 90 printf("%u", uid); 91 92 return true; 93} 94 95bool print_gid_object(gid_t gid) 96{ 97 if (flag_print_name) { 98 struct group* gr = getgrgid(gid); 99 printf("%s", gr ? gr->gr_name : "n/a"); 100 } else 101 printf("%u", gid); 102 return true; 103} 104 105bool print_gid_list() 106{ 107 int extra_gid_count = getgroups(0, nullptr); 108 if (extra_gid_count) { 109 auto* extra_gids = (gid_t*)alloca(extra_gid_count * sizeof(gid_t)); 110 int rc = getgroups(extra_gid_count, extra_gids); 111 112 if (rc < 0) { 113 perror("\ngetgroups"); 114 return false; 115 } 116 117 for (int g = 0; g < extra_gid_count; ++g) { 118 auto* gr = getgrgid(extra_gids[g]); 119 if (flag_print_name && gr) 120 printf("%s", gr->gr_name); 121 else 122 printf("%u", extra_gids[g]); 123 if (g != extra_gid_count - 1) 124 printf(" "); 125 } 126 } 127 return true; 128} 129 130bool print_full_id_list() 131{ 132 133 uid_t uid = getuid(); 134 gid_t gid = getgid(); 135 struct passwd* pw = getpwuid(uid); 136 struct group* gr = getgrgid(gid); 137 138 printf("uid=%u(%s) gid=%u(%s)", uid, pw ? pw->pw_name : "n/a", gid, gr ? gr->gr_name : "n/a"); 139 140 int extra_gid_count = getgroups(0, nullptr); 141 if (extra_gid_count) { 142 auto* extra_gids = (gid_t*)alloca(extra_gid_count * sizeof(gid_t)); 143 int rc = getgroups(extra_gid_count, extra_gids); 144 if (rc < 0) { 145 perror("\ngetgroups"); 146 return false; 147 } 148 printf(" groups="); 149 for (int g = 0; g < extra_gid_count; ++g) { 150 auto* gr = getgrgid(extra_gids[g]); 151 if (gr) 152 printf("%u(%s)", extra_gids[g], gr->gr_name); 153 else 154 printf("%u", extra_gids[g]); 155 if (g != extra_gid_count - 1) 156 printf(","); 157 } 158 } 159 return true; 160} 161 162int print_id_objects() 163{ 164 if (flag_print_uid) { 165 if (!print_uid_object(getuid())) 166 return 1; 167 } else if (flag_print_gid) { 168 if (!print_gid_object(getgid())) 169 return 1; 170 } else if (flag_print_gid_all) { 171 if (!print_gid_list()) 172 return 1; 173 } else { 174 if (!print_full_id_list()) 175 return 1; 176 } 177 178 printf("\n"); 179 return 0; 180}