Serenity Operating System
at master 101 lines 2.7 kB view raw
1/* 2 * Copyright (c) 2020, Fei Wu <f.eiwu@yahoo.com> 3 * Copyright (c) 2021, Brandon Pruitt <brapru@pm.me> 4 * Copyright (c) 2021, Maxime Friess <M4x1me@pm.me> 5 * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan62@gmail.com> 6 * 7 * SPDX-License-Identifier: BSD-2-Clause 8 */ 9 10#include <LibCore/ArgsParser.h> 11#include <LibCore/System.h> 12#include <LibMain/Main.h> 13#include <grp.h> 14#include <pwd.h> 15#include <unistd.h> 16 17ErrorOr<int> serenity_main(Main::Arguments arguments) 18{ 19 TRY(Core::System::pledge("stdio wpath rpath cpath fattr proc exec")); 20 TRY(Core::System::unveil("/etc/", "rwc")); 21 TRY(Core::System::unveil("/bin/rm", "x")); 22 23 DeprecatedString groupname; 24 25 Core::ArgsParser args_parser; 26 args_parser.add_positional_argument(groupname, "Group name", "group"); 27 args_parser.parse(arguments); 28 29 setgrent(); 30 auto* g = getgrnam(groupname.characters()); 31 32 // Check if the group exists 33 if (!g) { 34 warnln("group {} does not exist", groupname); 35 return 6; 36 } 37 auto gid = g->gr_gid; 38 endgrent(); 39 40 // Search if the group is the primary group of an user 41 setpwent(); 42 struct passwd* pw; 43 for (pw = getpwent(); pw; pw = getpwent()) { 44 if (pw->pw_gid == gid) 45 break; 46 } 47 48 // If pw is not NULL it means we ended prematurely, aka. the group was found as primary group of an user 49 if (pw) { 50 warnln("cannot remove the primary group of user '{}'", pw->pw_name); 51 endpwent(); 52 return 8; 53 } 54 55 endpwent(); 56 // We can now safely delete the group 57 58 // Create a temporary group file 59 char temp_group[] = "/etc/group.XXXXXX"; 60 StringView temp_group_view { temp_group, strlen(temp_group) }; 61 62 auto unlink_temp_files = [&] { 63 if (Core::System::unlink(temp_group_view).is_error()) 64 perror("unlink"); 65 }; 66 67 ArmedScopeGuard unlink_temp_files_guard = [&] { 68 unlink_temp_files(); 69 }; 70 71 int temp_group_fd = TRY(Core::System::mkstemp(temp_group)); 72 73 FILE* temp_group_file = fdopen(temp_group_fd, "w"); 74 if (!temp_group_file) { 75 perror("fdopen"); 76 return 1; 77 } 78 79 setgrent(); 80 for (auto* gr = getgrent(); gr; gr = getgrent()) { 81 if (gr->gr_gid != gid) { 82 if (putgrent(gr, temp_group_file) != 0) { 83 perror("failed to put an entry in the temporary group file"); 84 return 1; 85 } 86 } 87 } 88 endgrent(); 89 90 if (fclose(temp_group_file)) { 91 perror("fclose"); 92 return 1; 93 } 94 95 TRY(Core::System::chmod(temp_group_view, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); 96 TRY(Core::System::rename(temp_group_view, "/etc/group"sv)); 97 98 unlink_temp_files_guard.disarm(); 99 100 return 0; 101}