add usefun info on SIGINT handling peculiarities
[oweals/busybox.git] / loginutils / deluser.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * deluser (remove lusers from the system ;) for TinyLogin
4  *
5  * Copyright (C) 1999 by Lineo, inc. and John Beppu
6  * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7  * Unified with delgroup by Tito Ragusa <farmatito@tiscali.it>
8  *
9  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
10  *
11  */
12
13 #include "busybox.h"
14
15 /* where to start and stop deletion */
16 typedef struct {
17         size_t start;
18         size_t stop;
19 } Bounds;
20
21 /* An interesting side-effect of boundary()'s
22  * implementation is that the first user (typically root)
23  * cannot be removed.  Let's call it a feature. */
24 static inline Bounds boundary(const char *buffer, const char *login)
25 {
26         char needle[256];
27         char *start;
28         char *stop;
29         Bounds b;
30
31         snprintf(needle, 256, "\n%s:", login);
32         needle[255] = 0;
33         start = strstr(buffer, needle);
34         if (!start) {
35                 b.start = 0;
36                 b.stop = 0;
37                 return b;
38         }
39         start++;
40
41         stop = strchr(start, '\n');
42         b.start = start - buffer;
43         b.stop = stop - buffer;
44         return b;
45 }
46
47 /* grep -v ^login (except it only deletes the first match) */
48 /* ...in fact, I think I'm going to simplify this later */
49 static void del_line_matching(const char *login, const char *filename)
50 {
51         char *buffer;
52         FILE *passwd;
53         Bounds b;
54         struct stat statbuf;
55
56
57         if ((passwd = fopen_or_warn(filename, "r"))) {
58                 // Remove pointless const.
59                 xstat((char *)filename, &statbuf);
60                 buffer = (char *) xmalloc(statbuf.st_size * sizeof(char));
61                 fread(buffer, statbuf.st_size, sizeof(char), passwd);
62                 fclose(passwd);
63                 /* find the user to remove */
64                 b = boundary(buffer, login);
65                 if (b.stop != 0) {
66                         /* write the file w/o the user */
67                         if ((passwd = fopen_or_warn(filename, "w"))) {
68                                 fwrite(buffer, (b.start - 1), sizeof(char), passwd);
69                                 fwrite(&buffer[b.stop], (statbuf.st_size - b.stop), sizeof(char), passwd);
70                                 fclose(passwd);
71                         }
72                 } else {
73                         bb_error_msg("can't find '%s' in '%s'", login, filename);
74                 }
75                 free(buffer);
76         }
77 }
78
79 int deluser_main(int argc, char **argv)
80 {
81         if (argc != 2) {
82                 bb_show_usage();
83         } else {
84                 if (ENABLE_DELUSER && applet_name[3] == 'u') {
85                         del_line_matching(argv[1], bb_path_passwd_file);
86                         if (ENABLE_FEATURE_SHADOWPASSWDS)
87                                 del_line_matching(argv[1], bb_path_shadow_file);
88                 }
89                 del_line_matching(argv[1], bb_path_group_file);
90                 if (ENABLE_FEATURE_SHADOWPASSWDS)
91                         del_line_matching(argv[1], bb_path_gshadow_file);
92         }
93         return (EXIT_SUCCESS);
94 }
95
96 /* $Id: deluser.c,v 1.4 2003/07/14 20:20:45 andersen Exp $ */