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