1/* userdel.c - delete a user 2 * 3 * Copyright 2014 Ashwini Kumar <ak.ashwini1981@gmail.com> 4 * 5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/userdel.html 6 7USE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 8USE_USERDEL(OLDTOY(deluser, userdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 9 10config USERDEL 11 bool "userdel" 12 default n 13 help 14 usage: userdel [-r] USER 15 usage: deluser [-r] USER 16 17 Delete USER from the SYSTEM 18 19 -r remove home directory 20*/ 21 22#define FOR_userdel 23#include "toys.h" 24 25static void update_groupfiles(char *filename, char* username) 26{ 27 char *filenamesfx = NULL, *sfx = NULL, *line = NULL; 28 FILE *exfp, *newfp; 29 int ulen = strlen(username); 30 size_t allocated_length = 0; 31 struct flock lock; 32 33 filenamesfx = xmprintf("%s+", filename); 34 sfx = strchr(filenamesfx, '+'); 35 exfp = xfopen(filename, "r+"); 36 37 *sfx = '-'; 38 unlink(filenamesfx); 39 if (link(filename, filenamesfx)) error_msg("Can't create backup file"); 40 41 *sfx = '+'; 42 lock.l_type = F_WRLCK; 43 lock.l_whence = SEEK_SET; 44 lock.l_start = lock.l_len = 0; 45 46 if (fcntl(fileno(exfp), F_SETLK, &lock) < 0) 47 perror_msg("Couldn't lock file %s",filename); 48 49 lock.l_type = F_UNLCK; //unlocking at a later stage 50 51 newfp = xfopen(filenamesfx, "w+"); 52 53 while (getline(&line, &allocated_length, exfp) > 0) { 54 sprintf(toybuf, "%s:",username); 55 if (strncmp(line, toybuf, ulen+1)) { 56 char *n, *p = strrchr(line, ':'); 57 58 if (p && *++p && (n = strstr(p, username))) { 59 do { 60 if (n[ulen] == ',') { 61 *n = '\0'; 62 n += ulen + 1; 63 fprintf(newfp, "%s%s\n", line, n); 64 break; 65 } else if (!n[ulen]) { 66 if (n[-1] == ',') n[-1] = *n = '\0'; 67 if (n[-1] == ':') *n = '\0'; 68 fprintf(newfp, "%s%s\n", line, n); 69 break; 70 } else n += ulen; 71 } while (*n && (n=strstr(n, username))); 72 if (!n) fprintf(newfp, "%s\n", line); 73 } else fprintf(newfp, "%s\n", line); 74 } 75 } 76 free(line); 77 fcntl(fileno(exfp), F_SETLK, &lock); 78 fclose(exfp); 79 errno = 0; 80 fflush(newfp); 81 fsync(fileno(newfp)); 82 fclose(newfp); 83 rename(filenamesfx, filename); 84 if (errno){ 85 perror_msg("File Writing/Saving failed: "); 86 unlink(filenamesfx); 87 } 88 free(filenamesfx); 89} 90 91void userdel_main(void) 92{ 93 struct passwd *pwd = xgetpwnam(*toys.optargs); 94 95 update_password("/etc/passwd", pwd->pw_name, NULL); 96 update_password("/etc/shadow", pwd->pw_name, NULL); 97 98 // delete the group named USER, and remove user from group. 99 // could update_password() be used for this? 100 // not a good idea, as update_passwd() updates one entry at a time 101 // in this case it will be modifying the files as many times the 102 // USER appears in group database files. So the customized version 103 // of update_passwd() is here. 104 update_groupfiles("/etc/group", *toys.optargs); 105 update_groupfiles("/etc/gshadow", *toys.optargs); 106 107 if (FLAG(r)) { 108 char *arg[] = {"rm", "-fr", pwd->pw_dir, NULL, NULL}; 109 110 sprintf(toybuf, "/var/spool/mail/%s",pwd->pw_name); 111 arg[3] = toybuf; 112 xexec(arg); 113 } 114} 115