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_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 remove_file(pw->pw_dir, FILEUTILS_RECUR); 104 } else { 105 struct group *gr; 106 do_delgroup: 107 /* "delgroup GROUP" or "delgroup USER GROUP" */ 108 if (do_deluser < 0) { /* delgroup after deluser? */ 109 gr = getgrnam(name); 110 if (!gr) 111 return EXIT_SUCCESS; 112 } else { 113 gr = xgetgrnam(name); /* bail out if GROUP is wrong */ 114 } 115 if (!member) { 116 /* "delgroup GROUP" */ 117 struct passwd *pw; 118 /* Check if the group is in use */ 119 while ((pw = getpwent()) != NULL) { 120 if (pw->pw_gid == gr->gr_gid) 121 bb_error_msg_and_die("'%s' still has '%s' as their primary group!", 122 pw->pw_name, name); 123 } 124 //endpwent(); 125 } 126 pfile = bb_path_group_file; 127 if (ENABLE_FEATURE_SHADOWPASSWDS) 128 sfile = bb_path_gshadow_file; 129 } 130 131 /* Modify pfile, then sfile */ 132 do { 133 if (update_passwd(pfile, name, NULL, member) == -1) 134 return EXIT_FAILURE; 135 if (ENABLE_FEATURE_SHADOWPASSWDS) { 136 pfile = sfile; 137 sfile = NULL; 138 } 139 } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile); 140 141 if (do_deluser > 0) { 142 /* Delete user from all groups */ 143 if (update_passwd(bb_path_group_file, NULL, NULL, name) == -1) 144 return EXIT_FAILURE; 145 146 if (ENABLE_DELGROUP) { 147 /* "deluser USER" also should try to delete 148 * same-named group. IOW: do "delgroup USER" 149 */ 150// On debian deluser is a perl script that calls userdel. 151// From man userdel: 152// If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will 153// delete the group with the same name as the user. 154 do_deluser = -1; 155 goto do_delgroup; 156 } 157 } 158 return EXIT_SUCCESS; 159 } 160 /* Reached only if number of command line args is wrong */ 161 bb_show_usage(); 162} 163