]> git.pld-linux.org Git - projects/setup.git/blame - delpasswd.c
add etc/sub[ug]id
[projects/setup.git] / delpasswd.c
CommitLineData
dc189fa5 1/*
dc189fa5
JR
2 *
3 * Copyright (c) 2001 Michal Moskal <malekith@pld-linux.org>.
4 * Copyright (c) 2009 Jan Rękorajski <baggins@pld-linux.org>.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Michal Moskal.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY MICHAL MOSKAL AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *
35 *
5fe9e87e 36 * USAGE: delpasswd [-u|-g] name1 name2 ...
dc189fa5 37 *
5fe9e87e
JR
38 * Remove specified groups from /etc/{passwd,shadow,group}.
39 * It is usable as part of setup package, during upgrade where some system
40 * users/groups should be removed. UIDs/GIDs are *not* checked anyhow.
dc189fa5
JR
41 *
42 * Written for PLD Linux (http://www.pld-linux.org/) setup package.
43 *
44 * Compilation against uClibc:
45 * UCROOT=/usr/lib/bootdisk/usr
5fe9e87e
JR
46 * gcc -I$UCROOT/include -nostdlib -O2 delpasswd.c $UCROOT/lib/crt0.o \
47 * $UCROOT/lib/libc.a -lgcc -o delpasswd
48 * strip -R .comment -R .note delpasswd
dc189fa5 49 *
dc189fa5
JR
50 */
51
52#include <sys/types.h>
53#include <sys/mman.h>
54#include <sys/stat.h>
55#include <unistd.h>
56#include <fcntl.h>
57#include <stdlib.h>
dc189fa5
JR
58#include <string.h>
59#include <signal.h>
60
5fe9e87e
JR
61#if 0
62#define FILE1 "passwd"
63#define FILE2 "shadow"
64#define FILE3 "group"
65#define FILE4 "gshadow"
66#else
67#define FILE1 "/etc/passwd"
68#define FILE2 "/etc/shadow"
dc189fa5
JR
69#define FILE3 "/etc/group"
70#define FILE4 "/etc/gshadow"
5fe9e87e 71#endif
dc189fa5
JR
72
73/* #define OLD_LOCK */
74
75#define LOCK_FILE "/etc/.pwd.lock"
76
77/* maybe "-" or sth? */
78#define BACKUP ".old"
79
80/* #define SILENT */
81
82void eputs(const char *msg)
83{
84 write(2, msg, strlen(msg));
85}
86
87void fatal(const char *msg)
88{
89 eputs(msg);
90 eputs("\n");
91 exit(1);
92}
93
db127c35 94char *map_file(const char *name, ssize_t *sz)
dc189fa5
JR
95{
96 int fd;
97 void *ptr;
98 struct stat st;
99
100 fd = open(name, O_RDONLY);
101 if (fd == -1)
102 return NULL;
5fe9e87e
JR
103 if (fstat(fd, &st) < 0)
104 return NULL;
dc189fa5
JR
105 *sz = st.st_size;
106 ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
107 if (ptr == MAP_FAILED)
108 return NULL;
109
110 return ptr;
111}
112
5fe9e87e 113int exist(char *id, int id_len, int namesc, const char **names)
dc189fa5
JR
114{
115 int i;
116
5fe9e87e
JR
117 for (i = 0; i < namesc; i++) {
118 if (strlen(names[i]) == id_len && memcmp(id, names[i], id_len) == 0)
dc189fa5 119 return 1;
dc189fa5
JR
120 }
121
122 return 0;
123}
124
125void itoa(char *buf, long i)
126{
127 char tmp[32];
128 char *p;
129
130 if (i < 0) {
131 strcpy(buf, "-");
132 buf++;
133 i = -i;
134 }
135 if (i == 0) {
136 strcpy(buf, "0");
137 return;
138 }
139 for (p = tmp; i; i /= 10)
140 *p++ = (i % 10) + '0';
141 while (p > tmp)
142 *buf++ = *--p;
143 *buf = 0;
144}
145
146#ifndef OLD_LOCK
147int lock_fd = -1;
148void noop(int x)
149{
150 (void)x;
151}
152#endif
153
154int try_lock(const char *name)
155{
156#ifdef OLD_LOCK
157 char file[strlen(name) + 32], lock[strlen(name) + 32];
158 char buf[32];
159 int fd;
160 long pid;
161
162 strcpy(lock, name);
163 strcpy(file, name);
164 strcat(lock, ".lock");
165 itoa(buf, (long)getpid());
166 strcat(file, ".");
167 strcat(file, buf);
168
169 fd = open(file, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
170 if (fd < 0)
171 return -1;
172 write(fd, buf, strlen(buf));
173 close(fd);
174
175 if (link(file, lock) == 0) {
176 unlink(file);
177 return 0;
178 }
179
180 fd = open(lock, O_RDONLY);
181 if (fd < 0)
182 goto oops;
183 memset(buf, 0, sizeof(buf));
184 read(fd, buf, sizeof(buf));
185 pid = atol(buf);
186 if (pid == 0 || kill(pid, 0) != 0) {
187 /* stale lock */
188 unlink(file);
189 unlink(lock);
190 /* try again */
191 return try_lock(name);
192 }
193
194oops:
195 unlink(file);
196 return -1;
197#else
198 struct flock fl;
199
200 if (lock_fd != -1)
201 return -1;
202 lock_fd = open(LOCK_FILE, O_RDWR|O_CREAT, 0600);
203 if (lock_fd == -1)
204 return -1;
205 signal(SIGALRM, noop);
206 alarm(15);
207 memset(&fl, 0, sizeof(fl));
208 fl.l_type = F_WRLCK;
209 fl.l_whence = SEEK_SET;
210 if (fcntl(lock_fd, F_SETLKW, &fl) != 0) {
211 alarm(0);
212 close(lock_fd);
213 lock_fd = -1;
214 return -1;
215 }
216 alarm(0);
217
218 return 0;
219#endif
220}
221
222void unlock(const char *name)
223{
224#ifdef OLD_LOCK
225 char lock[strlen(name) + 32];
226
227 strcpy(lock, name);
228 strcat(lock, ".lock");
229 unlink(lock);
230#else
231 if (lock_fd != -1)
232 close(lock_fd);
233 lock_fd = -1;
234#endif
235}
236
237void lock(const char *name)
238{
239 int n;
240
241 n = 5;
242 while (n--) {
243 if (try_lock(name) == 0)
244 return;
245 eputs("waiting for lock...\n");
246 sleep(1);
247 }
248 fatal("cannot get lock");
249}
250
1370fb36
JR
251int verifyp(const char *old_name, int namesc, const char **names)
252{
70834cc5 253 char *old, *id;
db127c35 254 ssize_t i, old_sz;
1370fb36
JR
255
256 // Fail silently if file does not exist
257 if (access(old_name, F_OK) == -1)
258 return -1;
259
70834cc5 260 old = map_file(old_name, &old_sz);
1370fb36
JR
261 if (old == NULL)
262 fatal("cannot mmap old");
263
264 for (i = 0; i < old_sz; ) {
265 id = old + i;
266 while (i < old_sz && old[i] != ':' && old[i] != '\n')
267 i++;
268 if (i < old_sz && old[i] == ':') {
b23b9b3e 269 int id_len;
1370fb36
JR
270
271 id_len = i - (id - old);
272 while (i < old_sz && old[i] != '\n')
273 i++;
274 if (i < old_sz)
275 i++;
b23b9b3e 276
1370fb36
JR
277 if (exist(id, id_len, namesc, names))
278 return 1;
279 } else if (i < old_sz)
280 i++;
281 }
282 return 0;
283}
284
5fe9e87e
JR
285int delp(const char *old_name, const char *backup_name,
286 int namesc, const char **names)
dc189fa5 287{
5fe9e87e 288 char *old, *tmp, *id;
e665ab23 289 int fd;
db127c35 290 ssize_t i, old_sz;
dc189fa5 291
5fe9e87e
JR
292 // Fail silently if file does not exist
293 if (access(old_name, F_OK) == -1)
294 return -1;
dc189fa5 295
5fe9e87e
JR
296 lock(old_name);
297 tmp = map_file(old_name, &old_sz);
298 if (tmp == NULL)
299 fatal("cannot mmap old for backup");
300
301 fd = open(backup_name, O_WRONLY|O_CREAT|O_TRUNC, 0600);
dc189fa5
JR
302 if (fd < 0)
303 fatal("cannot make backup");
db127c35
AM
304 if (write(fd, tmp, old_sz) < 0)
305 fatal("writting to backup failed");
dc189fa5 306 close(fd);
5fe9e87e
JR
307
308 old = map_file(backup_name, &old_sz);
309 if (old == NULL)
310 fatal("cannot mmap old");
311
dc189fa5 312#ifndef SILENT
5fe9e87e
JR
313 eputs("removing from `");
314 eputs(old_name);
dc189fa5
JR
315 eputs("'\n");
316#endif /* SILENT */
317
5fe9e87e 318 fd = open(old_name, O_WRONLY|O_TRUNC);
dc189fa5 319 if (fd < 0)
5fe9e87e 320 fatal("cannot open old file");
dc189fa5 321
5fe9e87e 322 for (i = 0; i < old_sz; ) {
dc189fa5 323 id = old + i;
5fe9e87e 324 while (i < old_sz && old[i] != ':' && old[i] != '\n')
dc189fa5 325 i++;
5fe9e87e 326 if (i < old_sz && old[i] == ':') {
dc189fa5 327 int id_len, line_len;
dc189fa5
JR
328
329 id_len = i - (id - old);
5fe9e87e 330 while (i < old_sz && old[i] != '\n')
dc189fa5 331 i++;
5fe9e87e 332 if (i < old_sz)
dc189fa5 333 i++;
5fe9e87e
JR
334 line_len = i - (id - old);
335
336 if (!exist(id, id_len, namesc, names)) {
337 write(fd, id, line_len);
338 }
dc189fa5 339#ifndef SILENT
5fe9e87e
JR
340 else {
341 eputs(old_name);
342 eputs(": removing `");
343 write(2, id, id_len);
dc189fa5 344 eputs("'\n");
5fe9e87e 345 }
dc189fa5 346#endif /* SILENT */
5fe9e87e 347 } else if (i < old_sz)
dc189fa5
JR
348 i++;
349 }
dc189fa5 350
5fe9e87e
JR
351 close(fd);
352 unlock(old_name);
dc189fa5
JR
353
354 return 0;
355}
356
5fe9e87e 357int main(int argc, const char **argv)
dc189fa5 358{
5fe9e87e
JR
359 int what = 0;
360
361 if (argc < 3)
362 fatal("Usage: delpasswd [-u|-g] name1 name2 ... nameN");
363
364 if (strncmp(argv[1], "-u", 2) == 0)
365 what = 1;
366 else if (strncmp(argv[1], "-g", 2) == 0)
367 what = 2;
368
369 if (what == 0)
370 fatal("Usage: delpasswd [-u|-g] name1 name2 ... nameN");
371#if 1
372 if (what == 1) {
1370fb36
JR
373 if (verifyp(FILE1, argc-2, argv+2))
374 delp(FILE1, FILE1 BACKUP, argc-2, argv+2);
375 if (verifyp(FILE2, argc-2, argv+2))
376 delp(FILE2, FILE2 BACKUP, argc-2, argv+2);
5fe9e87e
JR
377 }
378 if (what == 2) {
1370fb36
JR
379 if (verifyp(FILE3, argc-2, argv+2))
380 delp(FILE3, FILE3 BACKUP, argc-2, argv+2);
381 if (verifyp(FILE4, argc-2, argv+2))
382 delp(FILE4, FILE4 BACKUP, argc-2, argv+2);
dc189fa5 383 }
dc189fa5 384#else
5fe9e87e 385 delp("test", "test.old", argc-2, argv+2);
dc189fa5
JR
386#endif
387 return 0;
388}
This page took 0.29586 seconds and 4 git commands to generate.