Use the correct buffer when calling dirname, improve an error message, and
[oweals/busybox.git] / deluser.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * deluser (remove lusers from the system ;) for TinyLogin
4  *
5  *
6  * Copyright (C) 1999 by Lineo, inc.
7  * Written by John Beppu <beppu@lineo.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  */
24
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "busybox.h"
31
32 #define PASSWD_FILE     "/etc/passwd"
33 #define GROUP_FILE      "/etc/group"
34
35 /* where to start and stop deletion */
36 typedef struct {
37         size_t start;
38         size_t stop;
39 } Bounds;
40
41 /* An interesting side-effect of boundary()'s
42  * implementation is that the first user (typically root)
43  * cannot be removed.  Let's call it a feature. */
44 static Bounds boundary(const char *buffer, const char *login)
45 {
46         char needle[256];
47         char *start;
48         char *stop;
49         Bounds b;
50
51         snprintf(needle, 256, "\n%s", login);
52         needle[255] = 0;
53         start = strstr(buffer, needle);
54         if (!start) {
55                 b.start = 0;
56                 b.stop = 0;
57                 return b;
58         }
59         start++;
60
61         stop = index(start, '\n');      /* index is a BSD-ism */
62         b.start = start - buffer;
63         b.stop = stop - buffer;
64         return b;
65 }
66
67 /* grep -v ^login (except it only deletes the first match) */
68 /* ...in fact, I think I'm going to simplify this later */
69 static int del_line_matching(char *login, char *filename)
70 {
71         char *buffer;
72         FILE *passwd;
73         size_t len;
74         Bounds b;
75         struct stat statbuf;
76
77         /* load into buffer */
78         passwd = fopen(filename, "r");
79         if (!passwd) {
80                 return 1;
81         }
82         stat(filename, &statbuf);
83         len = statbuf.st_size;
84         buffer = (char *) malloc(len * sizeof(char));
85
86         if (!buffer) {
87                 fclose(passwd);
88                 return 1;
89         }
90         fread(buffer, len, sizeof(char), passwd);
91
92         fclose(passwd);
93
94         /* find the user to remove */
95         b = boundary(buffer, login);
96         if (b.stop == 0) {
97                 free(buffer);
98                 return 1;
99         }
100
101         /* write the file w/o the user */
102         passwd = fopen(filename, "w");
103         if (!passwd) {
104                 return 1;
105         }
106         fwrite(buffer, (b.start - 1), sizeof(char), passwd);
107         fwrite(&buffer[b.stop], (len - b.stop), sizeof(char), passwd);
108
109         fclose(passwd);
110
111         return 0;
112 }
113
114 /* ________________________________________________________________________ */
115 int delgroup_main(int argc, char **argv)
116 {
117         /* int successful; */
118         int failure;
119
120         if (argc != 2) {
121                 show_usage();
122         } else {
123
124                 failure = del_line_matching(argv[1], GROUP_FILE);
125 #ifdef TLG_FEATURE_SHADOWPASSWDS
126                 if (access(GSHADOW_FILE, W_OK) == 0) {
127                         /* EDR the |= works if the error is not 0, so he had it wrong */
128                         failure |= del_line_matching(argv[1], GSHADOW_FILE);
129                 }
130 #endif                                                  /* TLG_FEATURE_SHADOWPASSWDS */
131                 /* if (!successful) { */
132                 if (failure) {
133                         error_msg_and_die("%s: Group could not be removed\n", argv[1]);
134                 }
135
136         }
137         return (EXIT_SUCCESS);
138 }
139
140 /* ________________________________________________________________________ */
141 int deluser_main(int argc, char **argv)
142 {
143         /* int successful; */
144         int failure;
145
146         if (argc != 2) {
147                 show_usage();
148         } else {
149
150                 failure = del_line_matching(argv[1], PASSWD_FILE);
151                 /* if (!successful) { */
152                 if (failure) {
153                         error_msg_and_die("%s: User could not be removed from %s\n",
154                                                           argv[1], PASSWD_FILE);
155                 }
156 #ifdef TLG_FEATURE_SHADOWPASSWDS
157                 failure = del_line_matching(argv[1], SHADOW_FILE);
158                 /* if (!successful) { */
159                 if (failure) {
160                         error_msg_and_die("%s: User could not be removed from %s\n",
161                                                           argv[1], SHADOW_FILE);
162                 }
163 #endif                                                  /* TLG_FEATURE_SHADOWPASSWDS */
164                 failure = del_line_matching(argv[1], GROUP_FILE);
165                 /* if (!successful) { */
166                 if (failure) {
167                         error_msg_and_die("%s: User could not be removed from %s\n",
168                                                           argv[1], GROUP_FILE);
169                 }
170
171         }
172         return (EXIT_SUCCESS);
173 }
174
175 /* $Id: deluser.c,v 1.1 2001/08/21 16:18:59 andersen Exp $ */