1/* vi: set sw=4 ts=4: */ 2/* 3 * deluser/delgroup implementation for busybox 4 * 5 * Copyright (C) 1999 by Lineo, inc. and John Beppu 6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> 7 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it> 8 * 9 * Licensed under GPLv2, see file LICENSE in this source tree. 10 */ 11//config:config DELUSER 12//config: bool "deluser (9.1 kb)" 13//config: default y 14//config: help 15//config: Utility for deleting a user account. 16//config: 17//config:config DELGROUP 18//config: bool "delgroup (6.4 kb)" 19//config: default y 20//config: help 21//config: Utility for deleting a group account. 22//config: 23//config:config FEATURE_DEL_USER_FROM_GROUP 24//config: bool "Support removing users from groups" 25//config: default y 26//config: depends on DELGROUP 27//config: help 28//config: If called with two non-option arguments, deluser 29//config: or delgroup will remove an user from a specified group. 30 31// APPLET_NOEXEC:name main location suid_type help 32//applet:IF_DELUSER( APPLET_NOEXEC(deluser, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, deluser)) 33//applet:IF_DELGROUP(APPLET_NOEXEC(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup)) 34 35//kbuild:lib-$(CONFIG_DELUSER) += deluser.o 36//kbuild:lib-$(CONFIG_DELGROUP) += deluser.o 37 38//usage:#define deluser_trivial_usage 39//usage: IF_LONG_OPTS("[--remove-home] ") "USER" 40//usage:#define deluser_full_usage "\n\n" 41//usage: "Delete USER from the system" 42// --remove-home is self-explanatory enough to put it in --help 43 44//usage:#define delgroup_trivial_usage 45//usage: IF_FEATURE_DEL_USER_FROM_GROUP("[USER] ")"GROUP" 46//usage:#define delgroup_full_usage "\n\n" 47//usage: "Delete group GROUP from the system" 48//usage: IF_FEATURE_DEL_USER_FROM_GROUP(" or user USER from group GROUP") 49 50#include "libbb.h" 51 52int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 53int deluser_main(int argc, char **argv) 54{ 55 /* User or group name */ 56 char *name; 57 /* Username (non-NULL only in "delgroup USER GROUP" case) */ 58 char *member; 59 /* Name of passwd or group file */ 60 const char *pfile; 61 /* Name of shadow or gshadow file */ 62 const char *sfile; 63 /* Are we deluser or delgroup? */ 64 int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u')); 65 66#if !ENABLE_LONG_OPTS 67 const int opt_delhome = 0; 68#else 69 int opt_delhome = 0; 70 if (do_deluser) { 71 opt_delhome = getopt32long(argv, "", 72 "remove-home\0" No_argument "\xff"); 73 argv += opt_delhome; 74 argc -= opt_delhome; 75 } 76#endif 77 78 if (geteuid() != 0) 79 bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root); 80 81 name = argv[1]; 82 member = NULL; 83 84 switch (argc) { 85 case 3: 86 if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || do_deluser) 87 break; 88 /* It's "delgroup USER GROUP" */ 89 member = name; 90 name = argv[2]; 91 /* Fallthrough */ 92 93 case 2: 94 if (do_deluser) { 95 /* "deluser USER" */ 96 struct passwd *pw; 97 98 pw = xgetpwnam(name); /* bail out if USER is wrong */ 99 pfile = bb_path_passwd_file; 100 if (ENABLE_FEATURE_SHADOWPASSWDS) 101 sfile = bb_path_shadow_file; 102 if (opt_delhome) { 103 struct stat st; 104 105 /* Make sure home is an actual directory before 106 * removing it (e.g. users with /dev/null as home) */ 107 if (stat(pw->pw_dir, &st) == 0 && S_ISDIR(st.st_mode)) 108 remove_file(pw->pw_dir, FILEUTILS_RECUR); 109 } 110 } else { 111 struct group *gr; 112 do_delgroup: 113 /* "delgroup GROUP" or "delgroup USER GROUP" */ 114 if (do_deluser < 0) { /* delgroup after deluser? */ 115 gr = getgrnam(name); 116 if (!gr) 117 return EXIT_SUCCESS; 118 } else { 119 gr = xgetgrnam(name); /* bail out if GROUP is wrong */ 120 } 121 if (!member) { 122 /* "delgroup GROUP" */ 123 struct passwd *pw; 124 /* Check if the group is in use */ 125 while ((pw = getpwent()) != NULL) { 126 if (pw->pw_gid == gr->gr_gid) 127 bb_error_msg_and_die("'%s' still has '%s' as their primary group!", 128 pw->pw_name, name); 129 } 130 //endpwent(); 131 } 132 pfile = bb_path_group_file; 133 if (ENABLE_FEATURE_SHADOWPASSWDS) 134 sfile = bb_path_gshadow_file; 135 } 136 137 /* Modify pfile, then sfile */ 138 do { 139 if (update_passwd(pfile, name, NULL, member) == -1) 140 return EXIT_FAILURE; 141 if (ENABLE_FEATURE_SHADOWPASSWDS) { 142 pfile = sfile; 143 sfile = NULL; 144 } 145 } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile); 146 147 if (do_deluser > 0) { 148 /* Delete user from all groups */ 149 if (update_passwd(bb_path_group_file, NULL, NULL, name) == -1) 150 return EXIT_FAILURE; 151 152 if (ENABLE_DELGROUP) { 153 /* "deluser USER" also should try to delete 154 * same-named group. IOW: do "delgroup USER" 155 */ 156// On debian deluser is a perl script that calls userdel. 157// From man userdel: 158// If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will 159// delete the group with the same name as the user. 160 do_deluser = -1; 161 goto do_delgroup; 162 } 163 } 164 return EXIT_SUCCESS; 165 } 166 /* Reached only if number of command line args is wrong */ 167 bb_show_usage(); 168} 169