1 /* vi: set sw=4 ts=4: */
3 * addgroup - add groups to /etc/group and /etc/gshadow
5 * Copyright (C) 1999 by Lineo, inc. and John Beppu
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 //config:config ADDGROUP
12 //config: bool "addgroup (8.8 kb)"
14 //config: select LONG_OPTS
16 //config: Utility for creating a new group account.
18 //config:config FEATURE_ADDUSER_TO_GROUP
19 //config: bool "Support adding users to groups"
21 //config: depends on ADDGROUP
23 //config: If called with two non-option arguments,
24 //config: addgroup will add an existing user to an
25 //config: existing group.
27 //applet:IF_ADDGROUP(APPLET_NOEXEC(addgroup, addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP, addgroup))
29 //kbuild:lib-$(CONFIG_ADDGROUP) += addgroup.o
31 //usage:#define addgroup_trivial_usage
32 //usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP"
33 //usage:#define addgroup_full_usage "\n\n"
34 //usage: "Add a group" IF_FEATURE_ADDUSER_TO_GROUP(" or add a user to a group") "\n"
35 //usage: "\n -g GID Group id"
36 //usage: "\n -S Create a system group"
40 #if CONFIG_LAST_SYSTEM_ID < CONFIG_FIRST_SYSTEM_ID
41 #error Bad LAST_SYSTEM_ID or FIRST_SYSTEM_ID in .config
43 #if CONFIG_LAST_ID < CONFIG_LAST_SYSTEM_ID
44 #error Bad LAST_ID or LAST_SYSTEM_ID in .config
47 #define OPT_GID (1 << 0)
48 #define OPT_SYSTEM_ACCOUNT (1 << 1)
50 static void xgroup_study(struct group
*g
)
52 unsigned max
= CONFIG_LAST_ID
;
54 /* Make sure gr_name is unused */
55 if (getgrnam(g
->gr_name
)) {
56 bb_error_msg_and_die("%s '%s' in use", "group", g
->gr_name
);
57 /* these format strings are reused in adduser and addgroup */
60 /* if a specific gid is requested, the --system switch and */
61 /* min and max values are overridden, and the range of valid */
62 /* gid values is set to [0, INT_MAX] */
63 if (!(option_mask32
& OPT_GID
)) {
64 if (option_mask32
& OPT_SYSTEM_ACCOUNT
) {
65 g
->gr_gid
= CONFIG_FIRST_SYSTEM_ID
;
66 max
= CONFIG_LAST_SYSTEM_ID
;
68 g
->gr_gid
= CONFIG_LAST_SYSTEM_ID
+ 1;
71 /* Check if the desired gid is free
72 * or find the first free one */
74 if (!getgrgid(g
->gr_gid
)) {
75 return; /* found free group: return */
77 if (option_mask32
& OPT_GID
) {
78 /* -g N, cannot pick gid other than N: error */
79 bb_error_msg_and_die("%s '%s' in use", "gid", itoa(g
->gr_gid
));
80 /* this format strings is reused in adduser and addgroup */
82 if (g
->gr_gid
== max
) {
83 /* overflowed: error */
84 bb_error_msg_and_die("no %cids left", 'g');
85 /* this format string is reused in adduser and addgroup */
91 /* append a new user to the passwd file */
92 static void new_group(char *group
, gid_t gid
)
97 /* make sure gid and group haven't already been allocated */
102 /* add entry to group */
103 p
= xasprintf("x:%u:", (unsigned) gr
.gr_gid
);
104 if (update_passwd(bb_path_group_file
, group
, p
, NULL
) < 0)
106 if (ENABLE_FEATURE_CLEAN_UP
)
108 #if ENABLE_FEATURE_SHADOWPASSWDS
109 /* /etc/gshadow fields:
111 * 2. Encrypted password.
112 * If set, non-members of the group can join the group
113 * by typing the password for that group using the newgrp command.
114 * If the value is of this field ! then no user is allowed
115 * to access the group using the newgrp command. A value of !!
116 * is treated the same as a value of ! only it indicates
117 * that a password has never been set before. If the value is null,
118 * only group members can log into the group.
119 * 3. Group administrators (comma delimited list).
120 * Group members listed here can add or remove group members
121 * using the gpasswd command.
122 * 4. Group members (comma delimited list).
124 /* Ignore errors: if file is missing we assume admin doesn't want it */
125 update_passwd(bb_path_gshadow_file
, group
, "!::", NULL
);
129 //FIXME: upstream addgroup has no short options! NOT COMPATIBLE!
130 static const char addgroup_longopts
[] ALIGN1
=
131 "gid\0" Required_argument
"g"
132 "system\0" No_argument
"S"
136 * addgroup will take a login_name as its first parameter.
138 * gid can be customized via command-line parameters.
139 * If called with two non-option arguments, addgroup
140 * will add an existing user to an existing group.
142 int addgroup_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
143 int addgroup_main(int argc UNUSED_PARAM
, char **argv
)
145 #if ENABLE_FEATURE_ADDUSER_TO_GROUP
148 const char *gid
= "0";
150 /* need to be root */
152 bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root
);
156 * addgroup --gid num group
157 * addgroup user group
158 * Check for min, max and missing args */
159 #if ENABLE_FEATURE_ADDUSER_TO_GROUP
162 getopt32long(argv
, "^" "g:S" "\0" "-1:?2", addgroup_longopts
,
165 /* move past the commandline options */
169 #if ENABLE_FEATURE_ADDUSER_TO_GROUP
173 if (opts
& OPT_GID
) {
174 /* -g was there, but "addgroup -g num user group"
179 /* check if group and user exist */
180 xuname2uid(argv
[0]); /* unknown user: exit */
181 gr
= xgetgrnam(argv
[1]); /* unknown group: exit */
182 /* check if user is already in this group */
183 for (; *(gr
->gr_mem
) != NULL
; (gr
->gr_mem
)++) {
184 if (strcmp(argv
[0], *(gr
->gr_mem
)) == 0) {
185 /* user is already in group: do nothing */
189 if (update_passwd(bb_path_group_file
, argv
[1], NULL
, argv
[0]) < 0) {
192 # if ENABLE_FEATURE_SHADOWPASSWDS
193 update_passwd(bb_path_gshadow_file
, argv
[1], NULL
, argv
[0]);
196 #endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
198 die_if_bad_username(argv
[0]);
199 new_group(argv
[0], xatou_range(gid
, 0, CONFIG_LAST_ID
));
201 /* Reached only on success */