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
23extern const char *__progname;
24
25
26static 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
35static void
36print_usage_and_exit(bool error)
37{
38	fprintf(error ? stderr : stdout, kUsage, __progname);
39	exit(error ? 1 : 0);
40}
41
42
43int
44main(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