source: MondoRescue/branches/3.3/mindi-busybox/loginutils/addgroup.c@ 3621

Last change on this file since 3621 was 3621, checked in by Bruno Cornec, 7 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.2 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * addgroup - add groups to /etc/group and /etc/gshadow
4 *
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>
8 *
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 *
11 */
12//config:config ADDGROUP
13//config: bool "addgroup"
14//config: default y
15//config: help
16//config: Utility for creating a new group account.
17//config:
18//config:config FEATURE_ADDGROUP_LONG_OPTIONS
19//config: bool "Enable long options"
20//config: default y
21//config: depends on ADDGROUP && LONG_OPTS
22//config: help
23//config: Support long options for the addgroup applet.
24//config:
25//config:config FEATURE_ADDUSER_TO_GROUP
26//config: bool "Support for adding users to groups"
27//config: default y
28//config: depends on ADDGROUP
29//config: help
30//config: If called with two non-option arguments,
31//config: addgroup will add an existing user to an
32//config: existing group.
33
34//applet:IF_ADDGROUP(APPLET(addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP))
35
36//kbuild:lib-$(CONFIG_ADDGROUP) += addgroup.o
37
38//usage:#define addgroup_trivial_usage
39//usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP"
40//usage:#define addgroup_full_usage "\n\n"
41//usage: "Add a group" IF_FEATURE_ADDUSER_TO_GROUP(" or add a user to a group") "\n"
42//usage: "\n -g GID Group id"
43//usage: "\n -S Create a system group"
44
45#include "libbb.h"
46
47#if CONFIG_LAST_SYSTEM_ID < CONFIG_FIRST_SYSTEM_ID
48#error Bad LAST_SYSTEM_ID or FIRST_SYSTEM_ID in .config
49#endif
50#if CONFIG_LAST_ID < CONFIG_LAST_SYSTEM_ID
51#error Bad LAST_ID or LAST_SYSTEM_ID in .config
52#endif
53
54#define OPT_GID (1 << 0)
55#define OPT_SYSTEM_ACCOUNT (1 << 1)
56
57static void xgroup_study(struct group *g)
58{
59 unsigned max = CONFIG_LAST_ID;
60
61 /* Make sure gr_name is unused */
62 if (getgrnam(g->gr_name)) {
63 bb_error_msg_and_die("%s '%s' in use", "group", g->gr_name);
64 /* these format strings are reused in adduser and addgroup */
65 }
66
67 /* if a specific gid is requested, the --system switch and */
68 /* min and max values are overridden, and the range of valid */
69 /* gid values is set to [0, INT_MAX] */
70 if (!(option_mask32 & OPT_GID)) {
71 if (option_mask32 & OPT_SYSTEM_ACCOUNT) {
72 g->gr_gid = CONFIG_FIRST_SYSTEM_ID;
73 max = CONFIG_LAST_SYSTEM_ID;
74 } else {
75 g->gr_gid = CONFIG_LAST_SYSTEM_ID + 1;
76 }
77 }
78 /* Check if the desired gid is free
79 * or find the first free one */
80 while (1) {
81 if (!getgrgid(g->gr_gid)) {
82 return; /* found free group: return */
83 }
84 if (option_mask32 & OPT_GID) {
85 /* -g N, cannot pick gid other than N: error */
86 bb_error_msg_and_die("%s '%s' in use", "gid", itoa(g->gr_gid));
87 /* this format strings is reused in adduser and addgroup */
88 }
89 if (g->gr_gid == max) {
90 /* overflowed: error */
91 bb_error_msg_and_die("no %cids left", 'g');
92 /* this format string is reused in adduser and addgroup */
93 }
94 g->gr_gid++;
95 }
96}
97
98/* append a new user to the passwd file */
99static void new_group(char *group, gid_t gid)
100{
101 struct group gr;
102 char *p;
103
104 /* make sure gid and group haven't already been allocated */
105 gr.gr_gid = gid;
106 gr.gr_name = group;
107 xgroup_study(&gr);
108
109 /* add entry to group */
110 p = xasprintf("x:%u:", (unsigned) gr.gr_gid);
111 if (update_passwd(bb_path_group_file, group, p, NULL) < 0)
112 exit(EXIT_FAILURE);
113 if (ENABLE_FEATURE_CLEAN_UP)
114 free(p);
115#if ENABLE_FEATURE_SHADOWPASSWDS
116 /* /etc/gshadow fields:
117 * 1. Group name.
118 * 2. Encrypted password.
119 * If set, non-members of the group can join the group
120 * by typing the password for that group using the newgrp command.
121 * If the value is of this field ! then no user is allowed
122 * to access the group using the newgrp command. A value of !!
123 * is treated the same as a value of ! only it indicates
124 * that a password has never been set before. If the value is null,
125 * only group members can log into the group.
126 * 3. Group administrators (comma delimited list).
127 * Group members listed here can add or remove group members
128 * using the gpasswd command.
129 * 4. Group members (comma delimited list).
130 */
131 /* Ignore errors: if file is missing we assume admin doesn't want it */
132 update_passwd(bb_path_gshadow_file, group, "!::", NULL);
133#endif
134}
135
136#if ENABLE_FEATURE_ADDGROUP_LONG_OPTIONS
137static const char addgroup_longopts[] ALIGN1 =
138 "gid\0" Required_argument "g"
139 "system\0" No_argument "S"
140 ;
141#endif
142
143/*
144 * addgroup will take a login_name as its first parameter.
145 *
146 * gid can be customized via command-line parameters.
147 * If called with two non-option arguments, addgroup
148 * will add an existing user to an existing group.
149 */
150int addgroup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
151int addgroup_main(int argc UNUSED_PARAM, char **argv)
152{
153 unsigned opts;
154 const char *gid = "0";
155
156 /* need to be root */
157 if (geteuid()) {
158 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
159 }
160#if ENABLE_FEATURE_ADDGROUP_LONG_OPTIONS
161 applet_long_options = addgroup_longopts;
162#endif
163 /* Syntax:
164 * addgroup group
165 * addgroup -g num group
166 * addgroup user group
167 * Check for min, max and missing args */
168 opt_complementary = "-1:?2";
169 opts = getopt32(argv, "g:S", &gid);
170 /* move past the commandline options */
171 argv += optind;
172 //argc -= optind;
173
174#if ENABLE_FEATURE_ADDUSER_TO_GROUP
175 if (argv[1]) {
176 struct group *gr;
177
178 if (opts & OPT_GID) {
179 /* -g was there, but "addgroup -g num user group"
180 * is a no-no */
181 bb_show_usage();
182 }
183
184 /* check if group and user exist */
185 xuname2uid(argv[0]); /* unknown user: exit */
186 gr = xgetgrnam(argv[1]); /* unknown group: exit */
187 /* check if user is already in this group */
188 for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) {
189 if (!strcmp(argv[0], *(gr->gr_mem))) {
190 /* user is already in group: do nothing */
191 return EXIT_SUCCESS;
192 }
193 }
194 if (update_passwd(bb_path_group_file, argv[1], NULL, argv[0]) < 0) {
195 return EXIT_FAILURE;
196 }
197# if ENABLE_FEATURE_SHADOWPASSWDS
198 update_passwd(bb_path_gshadow_file, argv[1], NULL, argv[0]);
199# endif
200 } else
201#endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
202 {
203 die_if_bad_username(argv[0]);
204 new_group(argv[0], xatou_range(gid, 0, CONFIG_LAST_ID));
205 }
206 /* Reached only on success */
207 return EXIT_SUCCESS;
208}
Note: See TracBrowser for help on using the repository browser.