/* vi: set sw=4 ts=4: */ /* * deluser/delgroup implementation for busybox * * Copyright (C) 1999 by Lineo, inc. and John Beppu * Copyright (C) 1999,2000,2001 by John Beppu * Copyright (C) 2007 by Tito Ragusa * * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config DELUSER //config: bool "deluser (9.1 kb)" //config: default y //config: help //config: Utility for deleting a user account. //config: //config:config DELGROUP //config: bool "delgroup (6.4 kb)" //config: default y //config: help //config: Utility for deleting a group account. //config: //config:config FEATURE_DEL_USER_FROM_GROUP //config: bool "Support removing users from groups" //config: default y //config: depends on DELGROUP //config: help //config: If called with two non-option arguments, deluser //config: or delgroup will remove an user from a specified group. // APPLET_NOEXEC:name main location suid_type help //applet:IF_DELUSER( APPLET_NOEXEC(deluser, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, deluser)) //applet:IF_DELGROUP(APPLET_NOEXEC(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup)) //kbuild:lib-$(CONFIG_DELUSER) += deluser.o //kbuild:lib-$(CONFIG_DELGROUP) += deluser.o //usage:#define deluser_trivial_usage //usage: IF_LONG_OPTS("[--remove-home] ") "USER" //usage:#define deluser_full_usage "\n\n" //usage: "Delete USER from the system" // --remove-home is self-explanatory enough to put it in --help //usage:#define delgroup_trivial_usage //usage: IF_FEATURE_DEL_USER_FROM_GROUP("[USER] ")"GROUP" //usage:#define delgroup_full_usage "\n\n" //usage: "Delete group GROUP from the system" //usage: IF_FEATURE_DEL_USER_FROM_GROUP(" or user USER from group GROUP") #include "libbb.h" int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int deluser_main(int argc, char **argv) { /* User or group name */ char *name; /* Username (non-NULL only in "delgroup USER GROUP" case) */ char *member; /* Name of passwd or group file */ const char *pfile; /* Name of shadow or gshadow file */ const char *sfile; /* Are we deluser or delgroup? */ int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u')); #if !ENABLE_LONG_OPTS const int opt_delhome = 0; #else int opt_delhome = 0; if (do_deluser) { opt_delhome = getopt32long(argv, "", "remove-home\0" No_argument "\xff"); argv += opt_delhome; argc -= opt_delhome; } #endif if (geteuid() != 0) bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root); name = argv[1]; member = NULL; switch (argc) { case 3: if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || do_deluser) break; /* It's "delgroup USER GROUP" */ member = name; name = argv[2]; /* Fallthrough */ case 2: if (do_deluser) { /* "deluser USER" */ struct passwd *pw; pw = xgetpwnam(name); /* bail out if USER is wrong */ pfile = bb_path_passwd_file; if (ENABLE_FEATURE_SHADOWPASSWDS) sfile = bb_path_shadow_file; if (opt_delhome) { struct stat st; /* Make sure home is an actual directory before * removing it (e.g. users with /dev/null as home) */ if (stat(pw->pw_dir, &st) == 0 && S_ISDIR(st.st_mode)) remove_file(pw->pw_dir, FILEUTILS_RECUR); } } else { struct group *gr; do_delgroup: /* "delgroup GROUP" or "delgroup USER GROUP" */ if (do_deluser < 0) { /* delgroup after deluser? */ gr = getgrnam(name); if (!gr) return EXIT_SUCCESS; } else { gr = xgetgrnam(name); /* bail out if GROUP is wrong */ } if (!member) { /* "delgroup GROUP" */ struct passwd *pw; /* Check if the group is in use */ while ((pw = getpwent()) != NULL) { if (pw->pw_gid == gr->gr_gid) bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pw->pw_name, name); } //endpwent(); } pfile = bb_path_group_file; if (ENABLE_FEATURE_SHADOWPASSWDS) sfile = bb_path_gshadow_file; } /* Modify pfile, then sfile */ do { if (update_passwd(pfile, name, NULL, member) == -1) return EXIT_FAILURE; if (ENABLE_FEATURE_SHADOWPASSWDS) { pfile = sfile; sfile = NULL; } } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile); if (do_deluser > 0) { /* Delete user from all groups */ if (update_passwd(bb_path_group_file, NULL, NULL, name) == -1) return EXIT_FAILURE; if (ENABLE_DELGROUP) { /* "deluser USER" also should try to delete * same-named group. IOW: do "delgroup USER" */ // On debian deluser is a perl script that calls userdel. // From man userdel: // If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will // delete the group with the same name as the user. do_deluser = -1; goto do_delgroup; } } return EXIT_SUCCESS; } /* Reached only if number of command line args is wrong */ bb_show_usage(); }