Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | /* |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 3 | * deluser/delgroup implementation for busybox |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 4 | * |
| 5 | * Copyright (C) 1999 by Lineo, inc. and John Beppu |
| 6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 7 | * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it> |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 8 | * |
Rob Landley | e9a7a62 | 2006-09-22 02:52:41 +0000 | [diff] [blame] | 9 | * Licensed under GPL version 2, see file LICENSE in this tarball for details. |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 10 | * |
| 11 | */ |
| 12 | |
Denis Vlasenko | b6adbf1 | 2007-05-26 19:00:18 +0000 | [diff] [blame] | 13 | #include "libbb.h" |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 14 | |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 15 | /* Status */ |
| 16 | #define STATUS_OK 0 |
| 17 | #define NAME_NOT_FOUND 1 |
| 18 | #define MEMBER_NOT_FOUND 2 |
| 19 | |
| 20 | static void del_line_matching(char **args, |
| 21 | const char *filename, |
| 22 | FILE *(*fopen_func)(const char *fileName, const char *mode)) |
Rob Landley | 81c40b3 | 2006-04-10 18:03:17 +0000 | [diff] [blame] | 23 | { |
Rob Landley | 81c40b3 | 2006-04-10 18:03:17 +0000 | [diff] [blame] | 24 | FILE *passwd; |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 25 | smallint error = NAME_NOT_FOUND; |
| 26 | char *name = (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) ? args[2] : args[1]; |
| 27 | char *line, *del; |
| 28 | char *new = xzalloc(1); |
Denis Vlasenko | f7996f3 | 2007-01-11 17:20:00 +0000 | [diff] [blame] | 29 | |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 30 | passwd = fopen_func(filename, "r"); |
| 31 | if (passwd) { |
| 32 | while ((line = xmalloc_fgets(passwd))) { |
| 33 | int len = strlen(name); |
Rob Landley | 81c40b3 | 2006-04-10 18:03:17 +0000 | [diff] [blame] | 34 | |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 35 | if (strncmp(line, name, len) == 0 |
| 36 | && line[len] == ':' |
| 37 | ) { |
| 38 | error = STATUS_OK; |
| 39 | if (ENABLE_FEATURE_DEL_USER_FROM_GROUP) { |
| 40 | struct group *gr; |
| 41 | char *p; |
| 42 | if (args[2] |
| 43 | /* There were two args on commandline */ |
| 44 | && (gr = getgrnam(name)) |
| 45 | /* The group was not deleted in the meanwhile */ |
| 46 | && (p = strrchr(line, ':')) |
| 47 | /* We can find a pointer to the last ':' */ |
| 48 | ) { |
| 49 | error = MEMBER_NOT_FOUND; |
| 50 | /* Move past ':' (worst case to '\0') and cut the line */ |
| 51 | p[1] = '\0'; |
| 52 | /* Reuse p */ |
| 53 | for (p = xzalloc(1); *gr->gr_mem != NULL; gr->gr_mem++) { |
| 54 | /* Add all the other group members */ |
| 55 | if (strcmp(args[1], *gr->gr_mem) != 0) { |
| 56 | del = p; |
| 57 | p = xasprintf("%s%s%s", p, p[0] ? "," : "", *gr->gr_mem); |
| 58 | free(del); |
| 59 | } else |
| 60 | error = STATUS_OK; |
| 61 | } |
| 62 | /* Recompose the line */ |
| 63 | line = xasprintf("%s%s\n", line, p); |
| 64 | if (ENABLE_FEATURE_CLEAN_UP) free(p); |
| 65 | } else |
| 66 | goto skip; |
| 67 | } |
Denis Vlasenko | c9bb677 | 2006-11-27 00:54:59 +0000 | [diff] [blame] | 68 | } |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 69 | del = new; |
| 70 | new = xasprintf("%s%s", new, line); |
| 71 | free(del); |
| 72 | skip: |
| 73 | free(line); |
| 74 | } |
| 75 | |
| 76 | if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd); |
| 77 | |
| 78 | if (error) { |
| 79 | if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && error == MEMBER_NOT_FOUND) { |
| 80 | /* Set the correct values for error message */ |
| 81 | filename = name; |
| 82 | name = args[1]; |
| 83 | } |
| 84 | bb_error_msg("can't find %s in %s", name, filename); |
| 85 | } else { |
| 86 | passwd = fopen_func(filename, "w"); |
| 87 | if (passwd) { |
| 88 | fputs(new, passwd); |
| 89 | if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd); |
| 90 | } |
Denis Vlasenko | c9bb677 | 2006-11-27 00:54:59 +0000 | [diff] [blame] | 91 | } |
Rob Landley | 81c40b3 | 2006-04-10 18:03:17 +0000 | [diff] [blame] | 92 | } |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 93 | free(new); |
Rob Landley | 81c40b3 | 2006-04-10 18:03:17 +0000 | [diff] [blame] | 94 | } |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 95 | |
Denis Vlasenko | 9b49a5e | 2007-10-11 10:05:36 +0000 | [diff] [blame] | 96 | int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 97 | int deluser_main(int argc, char **argv) |
| 98 | { |
Denis Vlasenko | 4b924f3 | 2007-05-30 00:29:55 +0000 | [diff] [blame] | 99 | if (argc == 2 |
| 100 | || (ENABLE_FEATURE_DEL_USER_FROM_GROUP |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 101 | && (applet_name[3] == 'g' && argc == 3)) |
Denis Vlasenko | c9bb677 | 2006-11-27 00:54:59 +0000 | [diff] [blame] | 102 | ) { |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 103 | if (geteuid()) |
| 104 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
Denis Vlasenko | 4b924f3 | 2007-05-30 00:29:55 +0000 | [diff] [blame] | 105 | |
| 106 | if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3) |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 107 | || ENABLE_DELUSER |
| 108 | || (ENABLE_DELGROUP && ENABLE_DESKTOP) |
| 109 | ) { |
| 110 | if (ENABLE_DELUSER |
| 111 | && (!ENABLE_DELGROUP || applet_name[3] == 'u') |
| 112 | ) { |
| 113 | del_line_matching(argv, bb_path_passwd_file, xfopen); |
| 114 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
| 115 | del_line_matching(argv, bb_path_shadow_file, fopen_or_warn); |
| 116 | } else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1])) |
| 117 | bb_error_msg_and_die("can't remove primary group of user %s", argv[1]); |
| 118 | } |
| 119 | del_line_matching(argv, bb_path_group_file, xfopen); |
Rob Landley | 81c40b3 | 2006-04-10 18:03:17 +0000 | [diff] [blame] | 120 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
Denis Vlasenko | be1a9d4 | 2007-04-15 08:43:23 +0000 | [diff] [blame] | 121 | del_line_matching(argv, bb_path_gshadow_file, fopen_or_warn); |
| 122 | return EXIT_SUCCESS; |
| 123 | } else |
| 124 | bb_show_usage(); |
Robert Griebl | 1fca558 | 2002-06-04 20:45:46 +0000 | [diff] [blame] | 125 | } |