summaryrefslogtreecommitdiffhomepage
path: root/loginutils/deluser.c
blob: 110cd63103de4c9f3823b9ada199c7d1fc077970 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* 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 <beppu@codepoet.org>
 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 *
 */

//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) {
		applet_long_options =
			"remove-home\0" No_argument "\xff";
		opt_delhome = getopt32(argv, "");
		argv += opt_delhome;
		argc -= opt_delhome;
	}
#endif

	if (geteuid() != 0)
		bb_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)
				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();
}