Bläddra i källkod

Utilities: Add groupdel

M4x1m3 4 år sedan
förälder
incheckning
39e622c400
2 ändrade filer med 167 tillägg och 0 borttagningar
  1. 45 0
      Base/usr/share/man/man8/groupdel.md
  2. 122 0
      Userland/Utilities/groupdel.cpp

+ 45 - 0
Base/usr/share/man/man8/groupdel.md

@@ -0,0 +1,45 @@
+## Name
+
+groupdel - delete a group
+
+## Synopsis
+
+```**sh
+# groupdel <group>
+```
+
+## Description
+
+This program deletes a group in the system.
+
+This program must be run as root.
+
+## Caveats
+
+You may not remove the primary group of any existing user. You must remove the user before you remove the group.
+
+You should manually check all file systems to ensure that no files remain owned by this group.
+
+You should manually check all users to ensure that no user remain in this group.
+
+## Exit Values
+
+* 0 - Success
+* 1 - Couldn't update the group file
+* 6 - Specified group doesn't exist
+* 8 - Can't remove user's primary group
+
+## Files
+
+* `/etc/group` - group information (such as GID) in this file is deleted.
+
+## Examples
+
+```sh
+# groupdel alice
+```
+
+## See Also
+
+* [`useradd`(8)](groupadd.md)
+

+ 122 - 0
Userland/Utilities/groupdel.cpp

@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2020, Fei Wu <f.eiwu@yahoo.com>
+ * Copyright (c) 2021, Brandon Pruitt <brapru@pm.me>
+ * Copyright (c) 2021, Maxime Friess <M4x1me@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibCore/ArgsParser.h>
+#include <LibCore/File.h>
+#include <ctype.h>
+#include <grp.h>
+#include <pwd.h>
+#include <unistd.h>
+
+int main(int argc, char** argv)
+{
+    if (pledge("stdio wpath rpath cpath fattr proc exec", nullptr) < 0) {
+        perror("pledge");
+        return 1;
+    }
+
+    if (unveil("/etc/", "rwc") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil("/bin/rm", "x") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    char const* groupname = nullptr;
+    gid_t gid = 0;
+
+    Core::ArgsParser args_parser;
+    args_parser.add_positional_argument(groupname, "Group name", "group");
+    args_parser.parse(argc, argv);
+
+    setgrent();
+    auto* g = getgrnam(groupname);
+    gid = g->gr_gid;
+    endgrent();
+
+    // Check if the group exists
+    if (!g) {
+        warnln("group {} does not exist", groupname);
+        return 6;
+    }
+
+    // Search if the group is the primary group of an user
+    setpwent();
+    struct passwd* pw;
+    for (pw = getpwent(); pw; pw = getpwent()) {
+        if (pw->pw_gid == gid)
+            break;
+    }
+
+    // If pw is not NULL it means we ended prematuraly, aka. the group was found as primary group of an user
+    if (pw) {
+        warnln("cannot remove the primary group of user '{}'", pw->pw_name);
+        endpwent();
+        return 8;
+    }
+
+    endpwent();
+    // We can now safely delete the group
+
+    // Create a temporary group file
+    char temp_group[] = "/etc/group.XXXXXX";
+
+    auto unlink_temp_files = [&] {
+        if (unlink(temp_group) < 0)
+            perror("unlink");
+    };
+
+    ArmedScopeGuard unlink_temp_files_guard = [&] {
+        unlink_temp_files();
+    };
+
+    auto temp_group_fd = mkstemp(temp_group);
+    if (temp_group_fd == -1) {
+        perror("failed to create temporary group file");
+        return 1;
+    }
+
+    FILE* temp_group_file = fdopen(temp_group_fd, "w");
+    if (!temp_group_file) {
+        perror("fdopen");
+        return 1;
+    }
+
+    setgrent();
+    for (auto* gr = getgrent(); gr; gr = getgrent()) {
+        if (gr->gr_gid != gid) {
+            if (putgrent(gr, temp_group_file) != 0) {
+                perror("failed to put an entry in the temporary group file");
+                return 1;
+            }
+        }
+    }
+    endgrent();
+
+    if (fclose(temp_group_file)) {
+        perror("fclose");
+        return 1;
+    }
+
+    if (chmod(temp_group, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
+        perror("chmod");
+        return 1;
+    }
+
+    if (rename(temp_group, "/etc/group") < 0) {
+        perror("failed to rename the temporary group file");
+        return 1;
+    }
+
+    unlink_temp_files_guard.disarm();
+
+    return 0;
+}