aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/usage.h4
-rw-r--r--loginutils/Config.in9
-rw-r--r--loginutils/addgroup.c143
-rw-r--r--scripts/defconfig1
4 files changed, 114 insertions, 43 deletions
diff --git a/include/usage.h b/include/usage.h
index f4edf0556..c729532e5 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -12,9 +12,9 @@
12#define __BB_USAGE_H__ 12#define __BB_USAGE_H__
13 13
14#define addgroup_trivial_usage \ 14#define addgroup_trivial_usage \
15 "[-g GID] group_name [user_name]" 15 "[-g GID]"USE_FEATURE_ADDUSER_TO_GROUP(" [user_name]")" group_name"
16#define addgroup_full_usage \ 16#define addgroup_full_usage \
17 "Add a group to the system" \ 17 "Add a group to the system"USE_FEATURE_ADDUSER_TO_GROUP(" or add an user to a group") \
18 "\n\nOptions:\n" \ 18 "\n\nOptions:\n" \
19 " -g GID Specify gid" 19 " -g GID Specify gid"
20 20
diff --git a/loginutils/Config.in b/loginutils/Config.in
index 03a638c00..1d52cdfe5 100644
--- a/loginutils/Config.in
+++ b/loginutils/Config.in
@@ -59,6 +59,15 @@ config ADDGROUP
59 help 59 help
60 Utility for creating a new group account. 60 Utility for creating a new group account.
61 61
62config FEATURE_ADDUSER_TO_GROUP
63 bool "Support for adding users to groups"
64 default n
65 depends on ADDGROUP
66 help
67 If called with two non-option arguments,
68 addgroup will add an existing user to an
69 existing group.
70
62config DELGROUP 71config DELGROUP
63 bool "delgroup" 72 bool "delgroup"
64 default n 73 default n
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c
index 78250a418..5aefda6ff 100644
--- a/loginutils/addgroup.c
+++ b/loginutils/addgroup.c
@@ -1,9 +1,10 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * addgroup - add users to /etc/passwd and /etc/shadow 3 * addgroup - add groups to /etc/group and /etc/gshadow
4 * 4 *
5 * Copyright (C) 1999 by Lineo, inc. and John Beppu 5 * Copyright (C) 1999 by Lineo, inc. and John Beppu
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> 6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
7 * 8 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 * 10 *
@@ -11,48 +12,40 @@
11 12
12#include "busybox.h" 13#include "busybox.h"
13 14
14/* make sure gr_name isn't taken, make sure gid is kosher 15static void xgroup_study(struct group *g)
15 * return 1 on failure */
16static int group_study(struct group *g)
17{ 16{
18 enum { max = 65000 }; 17 enum { max = 65000 };
19 FILE *etc_group; 18 /* Use a particular gid. */
20 gid_t desired; 19 int desired = (g->gr_gid > 0);
21 /* Using _r function to avoid static buffers pulled in */ 20
22 char buffer[256]; 21 /* Make sure gr_name is unused */
23 struct group grp; 22 if (getgrnam(g->gr_name)) {
24 struct group *result; 23 goto error;
25 24 }
26 etc_group = xfopen(bb_path_group_file, "r"); 25
27 26 /* Check if the desired gid is free or
28 /* make sure gr_name isn't taken, make sure gid is kosher */ 27 find the first free one */
29 desired = g->gr_gid; 28 do {
30 while (!fgetgrent_r(etc_group, &grp, buffer, sizeof(buffer), &result)) { 29 if (g->gr_gid == max) { /* out of bounds: exit */
31 if ((strcmp(grp.gr_name, g->gr_name)) == 0) { 30 bb_error_msg_and_die("no gids left");
32 bb_error_msg_and_die("%s: group already in use", g->gr_name);
33 } 31 }
34 if ((desired) && grp.gr_gid == desired) { 32 if (!getgrgid(g->gr_gid)) {
35 bb_error_msg_and_die("%d: gid already in use", 33 return; /* ok */
36 desired);
37 } 34 }
38 if ((grp.gr_gid > g->gr_gid) && (grp.gr_gid < max)) { 35 if (desired) { /* the desired gid is already in use: exit */
39 g->gr_gid = grp.gr_gid; 36 g->gr_name = itoa(g->gr_gid);
37 goto error;
40 } 38 }
41 } 39 g->gr_gid++;
42 if (ENABLE_FEATURE_CLEAN_UP) 40 } while (1);
43 fclose(etc_group);
44 41
45 /* gid */ 42error:
46 g->gr_gid++; 43 /* exit */
47 if (desired) { 44 bb_error_msg_and_die("%s: already in use", g->gr_name);
48 g->gr_gid = desired;
49 }
50 /* return 1; */
51 return 0;
52} 45}
53 46
54/* append a new user to the passwd file */ 47/* append a new user to the passwd file */
55static int addgroup(char *group, gid_t gid, const char *user) 48static void new_group(char *group, gid_t gid)
56{ 49{
57 FILE *file; 50 FILE *file;
58 struct group gr; 51 struct group gr;
@@ -60,16 +53,14 @@ static int addgroup(char *group, gid_t gid, const char *user)
60 /* make sure gid and group haven't already been allocated */ 53 /* make sure gid and group haven't already been allocated */
61 gr.gr_gid = gid; 54 gr.gr_gid = gid;
62 gr.gr_name = group; 55 gr.gr_name = group;
63 if (group_study(&gr)) 56 xgroup_study( &gr);
64 return 1;
65 57
66 /* add entry to group */ 58 /* add entry to group */
67 file = xfopen(bb_path_group_file, "a"); 59 file = xfopen(bb_path_group_file, "a");
68 /* group:passwd:gid:userlist */ 60 /* group:passwd:gid:userlist */
69 fprintf(file, "%s:%s:%d:%s\n", group, "x", gr.gr_gid, user); 61 fprintf(file, "%s:x:%d:\n", group, gr.gr_gid);
70 if (ENABLE_FEATURE_CLEAN_UP) 62 if (ENABLE_FEATURE_CLEAN_UP)
71 fclose(file); 63 fclose(file);
72
73#if ENABLE_FEATURE_SHADOWPASSWDS 64#if ENABLE_FEATURE_SHADOWPASSWDS
74 file = fopen_or_warn(bb_path_gshadow_file, "a"); 65 file = fopen_or_warn(bb_path_gshadow_file, "a");
75 if (file) { 66 if (file) {
@@ -78,15 +69,60 @@ static int addgroup(char *group, gid_t gid, const char *user)
78 fclose(file); 69 fclose(file);
79 } 70 }
80#endif 71#endif
72}
73
74#if ENABLE_FEATURE_ADDUSER_TO_GROUP
75static void add_user_to_group(char **args,
76 const char *path,
77 FILE *(*fopen_func)(const char *fileName, const char *mode))
78{
79 char *line;
80 int len = strlen(args[1]);
81 llist_t *plist = NULL;
82 FILE *group_file;
83
84 group_file = fopen_func(path, "r");
81 85
82 /* return 1; */ 86 if (!group_file) return;
83 return 0; 87
88 while ((line = xmalloc_getline(group_file))) {
89 /* Find the group */
90 if (!strncmp(line, args[1], len)
91 && line[len] == ':'
92 ) {
93 /* Add the new user */
94 line = xasprintf("%s%s%s", line,
95 last_char_is(line, ':') ? "" : ",",
96 args[0]);
97 }
98 llist_add_to_end(&plist, line);
99 }
100
101 if (ENABLE_FEATURE_CLEAN_UP) {
102 fclose(group_file);
103 group_file = fopen_func(path, "w");
104 while ((line = llist_pop(&plist))) {
105 if (group_file)
106 fprintf(group_file, "%s\n", line);
107 free(line);
108 }
109 if (group_file)
110 fclose(group_file);
111 } else {
112 group_file = fopen_func(path, "w");
113 if (group_file)
114 while ((line = llist_pop(&plist)))
115 fprintf(group_file, "%s\n", line);
116 }
84} 117}
118#endif
85 119
86/* 120/*
87 * addgroup will take a login_name as its first parameter. 121 * addgroup will take a login_name as its first parameter.
88 * 122 *
89 * gid can be customized via command-line parameters. 123 * gid can be customized via command-line parameters.
124 * If called with two non-option arguments, addgroup
125 * will add an existing user to an existing group.
90 */ 126 */
91int addgroup_main(int argc, char **argv); 127int addgroup_main(int argc, char **argv);
92int addgroup_main(int argc, char **argv) 128int addgroup_main(int argc, char **argv)
@@ -101,11 +137,36 @@ int addgroup_main(int argc, char **argv)
101 } 137 }
102 /* move past the commandline options */ 138 /* move past the commandline options */
103 argv += optind; 139 argv += optind;
140 argc -= optind;
104 141
105 /* need to be root */ 142 /* need to be root */
106 if (geteuid()) { 143 if (geteuid()) {
107 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); 144 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
108 } 145 }
109 146
110 return addgroup(argv[0], gid, argv[1] ? argv[1] : ""); 147#if ENABLE_FEATURE_ADDUSER_TO_GROUP
148 if (argc == 2) {
149 struct group *gr;
150
151 /* check if group and user exist */
152 xuname2uid(argv[0]); /* unknown user: exit */
153 xgroup2gid(argv[1]); /* unknown group: exit */
154 /* check if user is already in this group */
155 gr = getgrnam(argv[1]);
156 for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) {
157 if (!strcmp(argv[0], *(gr->gr_mem))) {
158 /* user is already in group: do nothing */
159 return EXIT_SUCCESS;
160 }
161 }
162 add_user_to_group(argv, bb_path_group_file, xfopen);
163#if ENABLE_FEATURE_SHADOWPASSWDS
164 add_user_to_group(argv, bb_path_gshadow_file, fopen_or_warn);
165#endif /* ENABLE_FEATURE_SHADOWPASSWDS */
166 } else
167#endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
168 new_group(argv[0], gid);
169
170 /* Reached only on success */
171 return EXIT_SUCCESS;
111} 172}
diff --git a/scripts/defconfig b/scripts/defconfig
index 42f3605da..6864b2fa6 100644
--- a/scripts/defconfig
+++ b/scripts/defconfig
@@ -347,6 +347,7 @@ CONFIG_FEATURE_SHADOWPASSWDS=y
347CONFIG_USE_BB_SHADOW=y 347CONFIG_USE_BB_SHADOW=y
348CONFIG_USE_BB_PWD_GRP=y 348CONFIG_USE_BB_PWD_GRP=y
349CONFIG_ADDGROUP=y 349CONFIG_ADDGROUP=y
350CONFIG_FEATURE_ADDUSER_TO_GROUP=y
350CONFIG_DELGROUP=y 351CONFIG_DELGROUP=y
351CONFIG_ADDUSER=y 352CONFIG_ADDUSER=y
352CONFIG_DELUSER=y 353CONFIG_DELUSER=y