busybox/loginutils/deluser.c
<<
>>
Prefs
   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