libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / bin / multiuser / groupmod.cpp
blob2fbb47d197c355d49907c46aa043482c89b26944
1 /*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <errno.h>
7 #include <getopt.h>
8 #include <grp.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
14 #include <set>
15 #include <string>
17 #include <OS.h>
19 #include <RegistrarDefs.h>
20 #include <user_group.h>
21 #include <util/KMessage.h>
23 #include "multiuser_utils.h"
26 extern const char *__progname;
29 static const char* kUsage =
30 "Usage: %s [ <options> ] <group name>\n"
31 "Creates a new group <group name>.\n"
32 "\n"
33 "Options:\n"
34 " -A, --add-user <user>\n"
35 " Add the user <user> to the group.\n"
36 " -h, --help\n"
37 " Print usage info.\n"
38 " -R, --remove-user <user>\n"
39 " Remove the user <user> from the group.\n"
42 static void
43 print_usage_and_exit(bool error)
45 fprintf(error ? stderr : stdout, kUsage, __progname);
46 exit(error ? 1 : 0);
50 int
51 main(int argc, const char* const* argv)
53 typedef std::set<std::string> StringSet;
55 StringSet usersToAdd;
56 StringSet usersToRemove;
58 while (true) {
59 static struct option sLongOptions[] = {
60 { "add-user", required_argument, 0, 'A' },
61 { "help", no_argument, 0, 'h' },
62 { "remove-user", required_argument, 0, 'A' },
63 { 0, 0, 0, 0 }
66 opterr = 0; // don't print errors
67 int c = getopt_long(argc, (char**)argv, "A:hR:", sLongOptions, NULL);
68 if (c == -1)
69 break;
72 switch (c) {
73 case 'A':
74 usersToAdd.insert(optarg);
75 break;
77 case 'h':
78 print_usage_and_exit(false);
79 break;
81 case 'R':
82 usersToRemove.insert(optarg);
83 break;
85 default:
86 print_usage_and_exit(true);
87 break;
91 if (optind != argc - 1)
92 print_usage_and_exit(true);
94 const char* group = argv[optind];
96 if (geteuid() != 0) {
97 fprintf(stderr, "Error: Only root may modify groups.\n");
98 exit(1);
101 // get the group
102 struct group* groupInfo = getgrnam(group);
103 if (groupInfo == NULL) {
104 fprintf(stderr, "Error: Group \"%s\" doesn't exist.\n", group);
105 exit(1);
108 // check, if anything needs to be done
109 if (usersToAdd.empty() && usersToRemove.empty()) {
110 fprintf(stderr, "Error: No modification specified.\n");
111 exit(1);
114 // prepare request for the registrar
115 KMessage message(BPrivate::B_REG_UPDATE_GROUP);
116 if (message.AddInt32("gid", groupInfo->gr_gid) != B_OK
117 || message.AddString("name", group) != B_OK
118 || message.AddString("password", groupInfo->gr_passwd) != B_OK
119 || message.AddBool("add group", false) != B_OK) {
120 fprintf(stderr, "Error: Out of memory!\n");
121 exit(1);
124 for (int32 i = 0; const char* user = groupInfo->gr_mem[i]; i++) {
125 if (usersToRemove.erase(user) > 0)
126 continue;
128 usersToAdd.insert(user);
131 if (!usersToRemove.empty()) {
132 fprintf(stderr, "Error: \"%s\" is not a member of group \"%s\"\n",
133 usersToRemove.begin()->c_str(), group);
134 exit(1);
137 // If the group doesn't have any more members, insert an empty string as an
138 // indicator for the registrar to remove all members.
139 if (usersToAdd.empty())
140 usersToAdd.insert("");
142 for (StringSet::const_iterator it = usersToAdd.begin();
143 it != usersToAdd.end(); ++it) {
144 if (message.AddString("members", it->c_str()) != B_OK) {
145 fprintf(stderr, "Error: Out of memory!\n");
146 exit(1);
150 // send the request
151 KMessage reply;
152 status_t error = send_authentication_request_to_registrar(message, reply);
153 if (error != B_OK) {
154 fprintf(stderr, "Error: Failed to create group: %s\n", strerror(error));
155 exit(1);
158 return 0;