diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 0da689c8b7..0e12b689ec 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -102,6 +102,7 @@ target_link_libraries(functrace LibDebug LibX86 LibMain) target_link_libraries(gml-format LibGUI LibMain) target_link_libraries(grep LibRegex LibMain) target_link_libraries(gron LibMain) +target_link_libraries(groupadd LibMain) target_link_libraries(groups LibMain) target_link_libraries(gunzip LibCompress LibMain) target_link_libraries(gzip LibCompress LibMain) diff --git a/Userland/Utilities/groupadd.cpp b/Userland/Utilities/groupadd.cpp index 0bb4f206be..4ff73317f4 100644 --- a/Userland/Utilities/groupadd.cpp +++ b/Userland/Utilities/groupadd.cpp @@ -2,90 +2,30 @@ * Copyright (c) 2019-2020, Jesse Buhagiar * Copyright (c) 2021, Brandon Pruitt * Copyright (c) 2021, Maxime Friess + * Copyright (c) 2022, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ #include -#include -#include -#include -#include +#include +#include +#include -constexpr gid_t GROUPS_GID = 100; - -int main(int argc, char** argv) +ErrorOr serenity_main(Main::Arguments arguments) { - if (pledge("stdio wpath rpath cpath chown", nullptr) < 0) { - perror("pledge"); - return 1; - } + TRY(Core::System::pledge("stdio wpath rpath cpath chown")); - int gid = 0; - char const* groupname = nullptr; + gid_t gid = 0; + StringView group_name; Core::ArgsParser args_parser; args_parser.add_option(gid, "Group ID (gid) for the new group", "gid", 'g', "gid"); - args_parser.add_positional_argument(groupname, "Name of the group (groupname)", "group"); + args_parser.add_positional_argument(group_name, "Name of the group (groupname)", "group"); + args_parser.parse(arguments); - args_parser.parse(argc, argv); - - // Let's run a quick sanity check on groupname - if (strpbrk(groupname, "\\/!@#$%^&*()~+=`:\n")) { - warnln("invalid character in groupname, {}", groupname); - return 1; - } - - // Disallow names starting with _ and - - if (groupname[0] == '_' || groupname[0] == '-' || !isalpha(groupname[0])) { - warnln("invalid groupname, {}", groupname); - return 1; - } - - if (getgrnam(groupname)) { - warnln("Group {} already exists!", groupname); - return 1; - } - - if (gid < 0) { - warnln("invalid gid {}!", gid); - return 3; - } - - // First, let's sort out the gid for the group - if (gid > 0) { - if (getgrgid(static_cast(gid))) { - warnln("gid {} already exists!", gid); - return 4; - } - } else { - for (gid = GROUPS_GID; getgrgid(static_cast(gid)); gid++) { - } - } - - if (gid < 0) { - warnln("invalid gid {}", gid); - return 3; - } - - FILE* grfile = fopen("/etc/group", "a"); - if (!grfile) { - perror("failed to open /etc/group"); - return 1; - } - - struct group g; - g.gr_name = const_cast(groupname); - g.gr_passwd = const_cast("x"); - g.gr_gid = static_cast(gid); - g.gr_mem = nullptr; - - if (putgrent(&g, grfile) < 0) { - perror("putpwent"); - return 1; - } - - fclose(grfile); + auto group = Core::Group { group_name, gid }; + TRY(Core::Group::add_group(group)); return 0; }