deluser: also remove user from /etc/group
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 12 Mar 2015 14:30:46 +0000 (15:30 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 12 Mar 2015 14:30:46 +0000 (15:30 +0100)
function                                             old     new   delta
update_passwd                                       1270    1470    +200
deluser_main                                         310     332     +22

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
libbb/update_passwd.c
loginutils/deluser.c

index a30af6f72322c27c345c271b7189791612f53aef..dc26ebd1d1a6a51afae912d9d10074e4120abcb8 100644 (file)
@@ -62,6 +62,8 @@ static void check_selinux_update_passwd(const char *username)
     only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd
     or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd
 
+ 8) delete a user from all groups: update_passwd(FILE, NULL, NULL, MEMBER)
+
  This function does not validate the arguments fed to it
  so the calling program should take care of that.
 
@@ -99,12 +101,13 @@ int FAST_FUNC update_passwd(const char *filename,
        if (filename == NULL)
                return ret;
 
-       check_selinux_update_passwd(name);
+       if (name)
+               check_selinux_update_passwd(name);
 
        /* New passwd file, "/etc/passwd+" for now */
        fnamesfx = xasprintf("%s+", filename);
        sfx_char = &fnamesfx[strlen(fnamesfx)-1];
-       name_colon = xasprintf("%s:", name);
+       name_colon = xasprintf("%s:", name ? name : "");
        user_len = strlen(name_colon);
 
        if (shadow)
@@ -167,6 +170,37 @@ int FAST_FUNC update_passwd(const char *filename,
                line = xmalloc_fgetline(old_fp);
                if (!line) /* EOF/error */
                        break;
+
+               if (!name && member) {
+                       /* Delete member from all groups */
+                       /* line is "GROUP:PASSWD:[member1[,member2]...]" */
+                       unsigned member_len = strlen(member);
+                       char *list = strrchr(line, ':');
+                       while (list) {
+                               list++;
+ next_list_element:
+                               if (strncmp(list, member, member_len) == 0) {
+                                       char c;
+                                       changed_lines++;
+                                       c = list[member_len];
+                                       if (c == '\0') {
+                                               if (list[-1] == ',')
+                                                       list--;
+                                               *list = '\0';
+                                               break;
+                                       }
+                                       if (c == ',') {
+                                               overlapping_strcpy(list, list + member_len + 1);
+                                               goto next_list_element;
+                                       }
+                                       changed_lines--;
+                               }
+                               list = strchr(list, ',');
+                       }
+                       fprintf(new_fp, "%s\n", line);
+                       goto next;
+               }
+
                if (strncmp(name_colon, line, user_len) != 0) {
                        fprintf(new_fp, "%s\n", line);
                        goto next;
index 01a9386bc577377f8db866c2452b736178f0552d..110cd63103de4c9f3823b9ada199c7d1fc077970 100644 (file)
@@ -114,16 +114,22 @@ int deluser_main(int argc, char **argv)
                        }
                } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile);
 
-               if (ENABLE_DELGROUP && do_deluser > 0) {
-                       /* "deluser USER" also should try to delete
-                        * same-named group. IOW: do "delgroup USER"
-                        */
+               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;
+                               do_deluser = -1;
+                               goto do_delgroup;
+                       }
                }
                return EXIT_SUCCESS;
        }