xref: /haiku/src/bin/multiuser/groupadd.cpp (revision 84cc2b9655c438c28cd0073991f41684d41d1fe8)
1 /*
2  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
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>
13 
14 #include <OS.h>
15 
16 #include <RegistrarDefs.h>
17 #include <user_group.h>
18 #include <util/KMessage.h>
19 
20 #include "multiuser_utils.h"
21 
22 
23 extern const char *__progname;
24 
25 
26 static const char* kUsage =
27 	"Usage: %s [ <options> ] <group name>\n"
28 	"Creates a new group <group name>.\n"
29 	"\n"
30 	"Options:\n"
31 	"  -h, --help\n"
32 	"    Print usage info.\n"
33 	;
34 
35 static void
36 print_usage_and_exit(bool error)
37 {
38 	fprintf(error ? stderr : stdout, kUsage, __progname);
39 	exit(error ? 1 : 0);
40 }
41 
42 
43 int
44 main(int argc, const char* const* argv)
45 {
46 	while (true) {
47 		static struct option sLongOptions[] = {
48 			{ "help", no_argument, 0, 'h' },
49 			{ 0, 0, 0, 0 }
50 		};
51 
52 		opterr = 0; // don't print errors
53 		int c = getopt_long(argc, (char**)argv, "h", sLongOptions, NULL);
54 		if (c == -1)
55 			break;
56 
57 
58 		switch (c) {
59 			case 'h':
60 				print_usage_and_exit(false);
61 				break;
62 
63 			default:
64 				print_usage_and_exit(true);
65 				break;
66 		}
67 	}
68 
69 	if (optind != argc - 1)
70 		print_usage_and_exit(true);
71 
72 	const char* group = argv[optind];
73 
74 	if (geteuid() != 0) {
75 		fprintf(stderr, "Error: Only root may add groups.\n");
76 		exit(1);
77 	}
78 
79 	// check, if group already exists
80 	if (getgrnam(group) != NULL) {
81 		fprintf(stderr, "Error: Group \"%s\" already exists.\n", group);
82 		exit(1);
83 	}
84 
85 	// find an unused GID
86 	gid_t gid = 100;
87 	while (getgrgid(gid) != NULL)
88 		gid++;
89 
90 	// prepare request for the registrar
91 	KMessage message(BPrivate::B_REG_UPDATE_GROUP);
92 	if (message.AddInt32("gid", gid) != B_OK
93 		|| message.AddString("name", group) != B_OK
94 		|| message.AddString("password", "x") != B_OK
95 		|| message.AddBool("add group", true) != B_OK) {
96 		fprintf(stderr, "Error: Out of memory!\n");
97 		exit(1);
98 	}
99 
100 	// send the request
101 	KMessage reply;
102 	status_t error = send_authentication_request_to_registrar(message, reply);
103 	if (error != B_OK) {
104 		fprintf(stderr, "Error: Failed to create group: %s\n", strerror(error));
105 		exit(1);
106 	}
107 
108 	return 0;
109 }
110