2002-06-04 20:45:46 +00:00
|
|
|
/* vi: set sw=4 ts=4: */
|
|
|
|
/*
|
|
|
|
* deluser (remove lusers from the system ;) for TinyLogin
|
|
|
|
*
|
|
|
|
* Copyright (C) 1999 by Lineo, inc. and John Beppu
|
|
|
|
* Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
|
2006-04-10 18:03:17 +00:00
|
|
|
* Unified with delgroup by Tito Ragusa <farmatito@tiscali.it>
|
2002-06-04 20:45:46 +00:00
|
|
|
*
|
2006-09-22 02:52:41 +00:00
|
|
|
* Licensed under GPL version 2, see file LICENSE in this tarball for details.
|
2002-06-04 20:45:46 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "busybox.h"
|
|
|
|
|
2006-04-10 18:03:17 +00:00
|
|
|
/* where to start and stop deletion */
|
|
|
|
typedef struct {
|
|
|
|
size_t start;
|
|
|
|
size_t stop;
|
|
|
|
} Bounds;
|
2002-06-04 20:45:46 +00:00
|
|
|
|
2006-04-10 18:03:17 +00:00
|
|
|
/* An interesting side-effect of boundary()'s
|
|
|
|
* implementation is that the first user (typically root)
|
|
|
|
* cannot be removed. Let's call it a feature. */
|
|
|
|
static inline Bounds boundary(const char *buffer, const char *login)
|
|
|
|
{
|
|
|
|
char needle[256];
|
|
|
|
char *start;
|
|
|
|
char *stop;
|
|
|
|
Bounds b;
|
2002-06-04 20:45:46 +00:00
|
|
|
|
2006-04-10 18:03:17 +00:00
|
|
|
snprintf(needle, 256, "\n%s:", login);
|
|
|
|
needle[255] = 0;
|
|
|
|
start = strstr(buffer, needle);
|
|
|
|
if (!start) {
|
|
|
|
b.start = 0;
|
|
|
|
b.stop = 0;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
start++;
|
2002-06-04 20:45:46 +00:00
|
|
|
|
2006-04-16 05:54:31 +00:00
|
|
|
stop = strchr(start, '\n');
|
2006-04-10 18:03:17 +00:00
|
|
|
b.start = start - buffer;
|
|
|
|
b.stop = stop - buffer;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* grep -v ^login (except it only deletes the first match) */
|
|
|
|
/* ...in fact, I think I'm going to simplify this later */
|
|
|
|
static void del_line_matching(const char *login, const char *filename)
|
2002-06-04 20:45:46 +00:00
|
|
|
{
|
2006-04-10 18:03:17 +00:00
|
|
|
char *buffer;
|
|
|
|
FILE *passwd;
|
|
|
|
Bounds b;
|
|
|
|
struct stat statbuf;
|
|
|
|
|
2002-06-04 20:45:46 +00:00
|
|
|
|
2006-10-26 23:25:17 +00:00
|
|
|
if ((passwd = fopen_or_warn(filename, "r"))) {
|
2006-09-12 21:42:17 +00:00
|
|
|
// Remove pointless const.
|
|
|
|
xstat((char *)filename, &statbuf);
|
2006-04-10 18:03:17 +00:00
|
|
|
buffer = (char *) xmalloc(statbuf.st_size * sizeof(char));
|
|
|
|
fread(buffer, statbuf.st_size, sizeof(char), passwd);
|
|
|
|
fclose(passwd);
|
|
|
|
/* find the user to remove */
|
|
|
|
b = boundary(buffer, login);
|
|
|
|
if (b.stop != 0) {
|
|
|
|
/* write the file w/o the user */
|
2006-10-26 23:25:17 +00:00
|
|
|
if ((passwd = fopen_or_warn(filename, "w"))) {
|
2006-04-10 18:03:17 +00:00
|
|
|
fwrite(buffer, (b.start - 1), sizeof(char), passwd);
|
|
|
|
fwrite(&buffer[b.stop], (statbuf.st_size - b.stop), sizeof(char), passwd);
|
|
|
|
fclose(passwd);
|
|
|
|
}
|
|
|
|
} else {
|
2006-10-14 02:23:43 +00:00
|
|
|
bb_error_msg("can't find '%s' in '%s'", login, filename);
|
2006-04-10 18:03:17 +00:00
|
|
|
}
|
|
|
|
free(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int deluser_main(int argc, char **argv)
|
|
|
|
{
|
2002-06-04 20:45:46 +00:00
|
|
|
if (argc != 2) {
|
2003-03-19 09:13:01 +00:00
|
|
|
bb_show_usage();
|
2002-06-04 20:45:46 +00:00
|
|
|
} else {
|
2006-10-03 21:00:43 +00:00
|
|
|
if (ENABLE_DELUSER && applet_name[3] == 'u') {
|
2006-04-10 18:03:17 +00:00
|
|
|
del_line_matching(argv[1], bb_path_passwd_file);
|
|
|
|
if (ENABLE_FEATURE_SHADOWPASSWDS)
|
|
|
|
del_line_matching(argv[1], bb_path_shadow_file);
|
2002-06-04 20:45:46 +00:00
|
|
|
}
|
2006-04-10 18:03:17 +00:00
|
|
|
del_line_matching(argv[1], bb_path_group_file);
|
|
|
|
if (ENABLE_FEATURE_SHADOWPASSWDS)
|
|
|
|
del_line_matching(argv[1], bb_path_gshadow_file);
|
2002-06-04 20:45:46 +00:00
|
|
|
}
|
|
|
|
return (EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2003-07-14 20:20:45 +00:00
|
|
|
/* $Id: deluser.c,v 1.4 2003/07/14 20:20:45 andersen Exp $ */
|