diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-27 00:54:59 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-27 00:54:59 +0000 |
commit | c9bb67787a0d48af33045a2d813faf44ed5d59b4 (patch) | |
tree | 82508111fa3dc475a52260b1096353b6bf5782d2 | |
parent | bf11e8942d39d9445f1f6cfb6716f58b4d8189d5 (diff) | |
download | busybox-w32-c9bb67787a0d48af33045a2d813faf44ed5d59b4.tar.gz busybox-w32-c9bb67787a0d48af33045a2d813faf44ed5d59b4.tar.bz2 busybox-w32-c9bb67787a0d48af33045a2d813faf44ed5d59b4.zip |
deluser: size reduction by 60 bytes.
patch from Tito <farmatito@tiscali.it>
-rw-r--r-- | loginutils/deluser.c | 110 |
1 files changed, 48 insertions, 62 deletions
diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 795dae49f..e33710175 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c | |||
@@ -12,85 +12,71 @@ | |||
12 | 12 | ||
13 | #include "busybox.h" | 13 | #include "busybox.h" |
14 | 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) | 15 | static void del_line_matching(const char *login, const char *filename) |
50 | { | 16 | { |
51 | char *buffer; | 17 | char *line; |
52 | FILE *passwd; | 18 | FILE *passwd; |
53 | Bounds b; | 19 | int len = strlen(login); |
54 | struct stat statbuf; | 20 | int found = 0; |
21 | llist_t *plist = NULL; | ||
22 | |||
23 | passwd = fopen_or_warn(filename, "r"); | ||
24 | if (!passwd) return; | ||
25 | |||
26 | while ((line = xmalloc_fgets(passwd))) { | ||
27 | if (!strncmp(line, login, len) | ||
28 | && line[len] == ':' | ||
29 | ) { | ||
30 | found++; | ||
31 | free(line); | ||
32 | } else { | ||
33 | llist_add_to_end(&plist, line); | ||
34 | } | ||
35 | } | ||
55 | 36 | ||
37 | if (!found) { | ||
38 | bb_error_msg("can't find '%s' in '%s'", login, filename); | ||
39 | if (!ENABLE_FEATURE_CLEAN_UP) return; | ||
40 | goto clean_up; | ||
41 | } | ||
56 | 42 | ||
57 | if ((passwd = fopen_or_warn(filename, "r"))) { | 43 | if (ENABLE_FEATURE_CLEAN_UP) |
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); | 44 | fclose(passwd); |
63 | /* find the user to remove */ | 45 | |
64 | b = boundary(buffer, login); | 46 | passwd = fopen_or_warn(filename, "w"); |
65 | if (b.stop != 0) { | 47 | if (passwd) { |
66 | /* write the file w/o the user */ | 48 | if (ENABLE_FEATURE_CLEAN_UP) { |
67 | if ((passwd = fopen_or_warn(filename, "w"))) { | 49 | clean_up: |
68 | fwrite(buffer, (b.start - 1), sizeof(char), passwd); | 50 | while ((line = llist_pop(&plist))) { |
69 | fwrite(&buffer[b.stop], (statbuf.st_size - b.stop), sizeof(char), passwd); | 51 | if (found) fputs(line, passwd); |
70 | fclose(passwd); | 52 | free(line); |
71 | } | 53 | } |
54 | fclose(passwd); | ||
72 | } else { | 55 | } else { |
73 | bb_error_msg("can't find '%s' in '%s'", login, filename); | 56 | /* found != 0 here, no need to check */ |
57 | while ((line = llist_pop(&plist))) | ||
58 | fputs(line, passwd); | ||
74 | } | 59 | } |
75 | free(buffer); | ||
76 | } | 60 | } |
77 | } | 61 | } |
78 | 62 | ||
79 | int deluser_main(int argc, char **argv) | 63 | int deluser_main(int argc, char **argv) |
80 | { | 64 | { |
81 | if (argc != 2) { | 65 | if (argc != 2) |
82 | bb_show_usage(); | 66 | bb_show_usage(); |
83 | } else { | 67 | |
84 | if (ENABLE_DELUSER && applet_name[3] == 'u') { | 68 | if (ENABLE_DELUSER |
85 | del_line_matching(argv[1], bb_path_passwd_file); | 69 | && (!ENABLE_DELGROUP || applet_name[3] == 'u') |
86 | if (ENABLE_FEATURE_SHADOWPASSWDS) | 70 | ) { |
87 | del_line_matching(argv[1], bb_path_shadow_file); | 71 | del_line_matching(argv[1], bb_path_passwd_file); |
88 | } | ||
89 | del_line_matching(argv[1], bb_path_group_file); | ||
90 | if (ENABLE_FEATURE_SHADOWPASSWDS) | 72 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
91 | del_line_matching(argv[1], bb_path_gshadow_file); | 73 | del_line_matching(argv[1], bb_path_shadow_file); |
92 | } | 74 | } |
93 | return (EXIT_SUCCESS); | 75 | del_line_matching(argv[1], bb_path_group_file); |
76 | if (ENABLE_FEATURE_SHADOWPASSWDS) | ||
77 | del_line_matching(argv[1], bb_path_gshadow_file); | ||
78 | |||
79 | return EXIT_SUCCESS; | ||
94 | } | 80 | } |
95 | 81 | ||
96 | /* $Id: deluser.c,v 1.4 2003/07/14 20:20:45 andersen Exp $ */ | 82 | /* $Id: deluser.c,v 1.4 2003/07/14 20:20:45 andersen Exp $ */ |