Contents of /tags/mkinitrd-6_1_12/busybox/loginutils/addgroup.c
Parent Directory | Revision Log
Revision 939 -
(show annotations)
(download)
Tue Nov 17 21:24:51 2009 UTC (14 years, 10 months ago) by niro
File MIME type: text/plain
File size: 4403 byte(s)
Tue Nov 17 21:24:51 2009 UTC (14 years, 10 months ago) by niro
File MIME type: text/plain
File size: 4403 byte(s)
tagged 'mkinitrd-6_1_12'
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 tarball for details. |
10 | * |
11 | */ |
12 | |
13 | #include "libbb.h" |
14 | |
15 | static void xgroup_study(struct group *g) |
16 | { |
17 | /* Make sure gr_name is unused */ |
18 | if (getgrnam(g->gr_name)) { |
19 | goto error; |
20 | } |
21 | |
22 | /* Check if the desired gid is free |
23 | * or find the first free one */ |
24 | while (1) { |
25 | if (!getgrgid(g->gr_gid)) { |
26 | return; /* found free group: return */ |
27 | } |
28 | if (option_mask32) { |
29 | /* -g N, cannot pick gid other than N: error */ |
30 | g->gr_name = itoa(g->gr_gid); |
31 | goto error; |
32 | } |
33 | g->gr_gid++; |
34 | if (g->gr_gid <= 0) { |
35 | /* overflowed: error */ |
36 | bb_error_msg_and_die("no gids left"); |
37 | } |
38 | } |
39 | |
40 | error: |
41 | /* exit */ |
42 | bb_error_msg_and_die("group %s already exists", g->gr_name); |
43 | } |
44 | |
45 | /* append a new user to the passwd file */ |
46 | static void new_group(char *group, gid_t gid) |
47 | { |
48 | FILE *file; |
49 | struct group gr; |
50 | |
51 | /* make sure gid and group haven't already been allocated */ |
52 | gr.gr_gid = gid; |
53 | gr.gr_name = group; |
54 | xgroup_study(&gr); |
55 | |
56 | /* add entry to group */ |
57 | file = xfopen(bb_path_group_file, "a"); |
58 | /* group:passwd:gid:userlist */ |
59 | fprintf(file, "%s:x:%u:\n", group, (unsigned)gr.gr_gid); |
60 | if (ENABLE_FEATURE_CLEAN_UP) |
61 | fclose(file); |
62 | #if ENABLE_FEATURE_SHADOWPASSWDS |
63 | file = fopen_or_warn(bb_path_gshadow_file, "a"); |
64 | if (file) { |
65 | fprintf(file, "%s:!::\n", group); |
66 | if (ENABLE_FEATURE_CLEAN_UP) |
67 | fclose(file); |
68 | } |
69 | #endif |
70 | } |
71 | |
72 | #if ENABLE_FEATURE_ADDUSER_TO_GROUP |
73 | static void add_user_to_group(char **args, |
74 | const char *path, |
75 | FILE* FAST_FUNC (*fopen_func)(const char *fileName, const char *mode)) |
76 | { |
77 | char *line; |
78 | int len = strlen(args[1]); |
79 | llist_t *plist = NULL; |
80 | FILE *group_file; |
81 | |
82 | group_file = fopen_func(path, "r"); |
83 | |
84 | if (!group_file) return; |
85 | |
86 | while ((line = xmalloc_fgetline(group_file)) != NULL) { |
87 | /* Find the group */ |
88 | if (!strncmp(line, args[1], len) |
89 | && line[len] == ':' |
90 | ) { |
91 | /* Add the new user */ |
92 | line = xasprintf("%s%s%s", line, |
93 | last_char_is(line, ':') ? "" : ",", |
94 | args[0]); |
95 | } |
96 | llist_add_to_end(&plist, line); |
97 | } |
98 | |
99 | if (ENABLE_FEATURE_CLEAN_UP) { |
100 | fclose(group_file); |
101 | group_file = fopen_func(path, "w"); |
102 | while ((line = llist_pop(&plist))) { |
103 | if (group_file) |
104 | fprintf(group_file, "%s\n", line); |
105 | free(line); |
106 | } |
107 | if (group_file) |
108 | fclose(group_file); |
109 | } else { |
110 | group_file = fopen_func(path, "w"); |
111 | if (group_file) |
112 | while ((line = llist_pop(&plist))) |
113 | fprintf(group_file, "%s\n", line); |
114 | } |
115 | } |
116 | #endif |
117 | |
118 | /* |
119 | * addgroup will take a login_name as its first parameter. |
120 | * |
121 | * gid can be customized via command-line parameters. |
122 | * If called with two non-option arguments, addgroup |
123 | * will add an existing user to an existing group. |
124 | */ |
125 | int addgroup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
126 | int addgroup_main(int argc UNUSED_PARAM, char **argv) |
127 | { |
128 | char *group; |
129 | gid_t gid = 0; |
130 | |
131 | /* need to be root */ |
132 | if (geteuid()) { |
133 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
134 | } |
135 | |
136 | /* Syntax: |
137 | * addgroup group |
138 | * addgroup -g num group |
139 | * addgroup user group |
140 | * Check for min, max and missing args */ |
141 | opt_complementary = "-1:?2"; |
142 | if (getopt32(argv, "g:", &group)) { |
143 | gid = xatoul_range(group, 0, ((unsigned long)(gid_t)ULONG_MAX) >> 1); |
144 | } |
145 | /* move past the commandline options */ |
146 | argv += optind; |
147 | //argc -= optind; |
148 | |
149 | #if ENABLE_FEATURE_ADDUSER_TO_GROUP |
150 | if (argv[1]) { |
151 | struct group *gr; |
152 | |
153 | if (option_mask32) { |
154 | /* -g was there, but "addgroup -g num user group" |
155 | * is a no-no */ |
156 | bb_show_usage(); |
157 | } |
158 | |
159 | /* check if group and user exist */ |
160 | xuname2uid(argv[0]); /* unknown user: exit */ |
161 | xgroup2gid(argv[1]); /* unknown group: exit */ |
162 | /* check if user is already in this group */ |
163 | gr = getgrnam(argv[1]); |
164 | for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) { |
165 | if (!strcmp(argv[0], *(gr->gr_mem))) { |
166 | /* user is already in group: do nothing */ |
167 | return EXIT_SUCCESS; |
168 | } |
169 | } |
170 | add_user_to_group(argv, bb_path_group_file, xfopen); |
171 | #if ENABLE_FEATURE_SHADOWPASSWDS |
172 | add_user_to_group(argv, bb_path_gshadow_file, fopen_or_warn); |
173 | #endif |
174 | } else |
175 | #endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */ |
176 | { |
177 | die_if_bad_username(argv[0]); |
178 | new_group(argv[0], gid); |
179 | |
180 | } |
181 | /* Reached only on success */ |
182 | return EXIT_SUCCESS; |
183 | } |