diff options
Diffstat (limited to 'toys/pending/userdel.c')
-rw-r--r-- | toys/pending/userdel.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/toys/pending/userdel.c b/toys/pending/userdel.c new file mode 100644 index 00000000..8619a620 --- /dev/null +++ b/toys/pending/userdel.c @@ -0,0 +1,116 @@ +/* userdel.c - delete a user + * + * Copyright 2014 Ashwini Kumar <ak.ashwini1981@gmail.com> + * + * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/userdel.html + +USE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) +USE_USERDEL(OLDTOY(deluser, userdel, OPTSTR_userdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) + +config USERDEL + bool "userdel" + default n + help + usage: userdel [-r] USER + usage: deluser [-r] USER + + Options: + -r remove home directory + Delete USER from the SYSTEM +*/ + +#define FOR_userdel +#include "toys.h" + +static void update_groupfiles(char *filename, char* username) +{ + char *filenamesfx = NULL, *sfx = NULL, *line = NULL; + FILE *exfp, *newfp; + int ulen = strlen(username); + struct flock lock; + + filenamesfx = xmprintf("%s+", filename); + sfx = strchr(filenamesfx, '+'); + exfp = xfopen(filename, "r+"); + + *sfx = '-'; + unlink(filenamesfx); + if (link(filename, filenamesfx)) error_msg("Can't create backup file"); + + *sfx = '+'; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = lock.l_len = 0; + + if (fcntl(fileno(exfp), F_SETLK, &lock) < 0) + perror_msg("Couldn't lock file %s",filename); + + lock.l_type = F_UNLCK; //unlocking at a later stage + + newfp = xfopen(filenamesfx, "w+"); + + while ((line = get_line(fileno(exfp))) != NULL){ + sprintf(toybuf, "%s:",username); + if (!strncmp(line, toybuf, ulen+1)) goto LOOP; + else { + char *n, *p = strrchr(line, ':'); + + if (p && *++p && (n = strstr(p, username))) { + do { + if (n[ulen] == ',') { + *n = '\0'; + n += ulen + 1; + fprintf(newfp, "%s%s\n", line, n); + break; + } else if (!n[ulen]) { + if (n[-1] == ',') n[-1] = *n = '\0'; + if (n[-1] == ':') *n = '\0'; + fprintf(newfp, "%s%s\n", line, n); + break; + } else n += ulen; + } while (*n && (n=strstr(n, username))); + if (!n) fprintf(newfp, "%s\n", line); + } else fprintf(newfp, "%s\n", line); + } +LOOP: + free(line); + } + fcntl(fileno(exfp), F_SETLK, &lock); + fclose(exfp); + errno = 0; + fflush(newfp); + fsync(fileno(newfp)); + fclose(newfp); + rename(filenamesfx, filename); + if (errno){ + perror_msg("File Writing/Saving failed: "); + unlink(filenamesfx); + } + free(filenamesfx); +} + +void userdel_main(void) +{ + struct passwd *pwd = NULL; + + pwd = xgetpwnam(*toys.optargs); + update_password("/etc/passwd", pwd->pw_name, NULL); + update_password("/etc/shadow", pwd->pw_name, NULL); + + // delete the group named USER, and remove user from group. + // could update_password() be used for this? + // not a good idea, as update_passwd() updates one entry at a time + // in this case it will be modifying the files as many times the + // USER appears in group database files. So the customized version + // of update_passwd() is here. + update_groupfiles("/etc/group", *toys.optargs); + update_groupfiles("/etc/gshadow", *toys.optargs); + + if (toys.optflags & FLAG_r) { + char *arg[] = {"rm", "-fr", pwd->pw_dir, NULL, NULL}; + + sprintf(toybuf, "/var/spool/mail/%s",pwd->pw_name); + arg[3] = toybuf; + xexec(arg); + } +} |