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 7 USE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 8 USE_USERDEL(OLDTOY(deluser, userdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 9 10 config 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 25 static 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 struct flock lock; 31 32 filenamesfx = xmprintf("%s+", filename); 33 sfx = strchr(filenamesfx, '+'); 34 exfp = xfopen(filename, "r+"); 35 36 *sfx = '-'; 37 unlink(filenamesfx); 38 if (link(filename, filenamesfx)) error_msg("Can't create backup file"); 39 40 *sfx = '+'; 41 lock.l_type = F_WRLCK; 42 lock.l_whence = SEEK_SET; 43 lock.l_start = lock.l_len = 0; 44 45 if (fcntl(fileno(exfp), F_SETLK, &lock) < 0) 46 perror_msg("Couldn't lock file %s",filename); 47 48 lock.l_type = F_UNLCK; //unlocking at a later stage 49 50 newfp = xfopen(filenamesfx, "w+"); 51 52 while ((line = get_line(fileno(exfp))) != NULL){ 53 sprintf(toybuf, "%s:",username); 54 if (!strncmp(line, toybuf, ulen+1)) goto LOOP; 55 else { 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 LOOP: 76 free(line); 77 } 78 fcntl(fileno(exfp), F_SETLK, &lock); 79 fclose(exfp); 80 errno = 0; 81 fflush(newfp); 82 fsync(fileno(newfp)); 83 fclose(newfp); 84 rename(filenamesfx, filename); 85 if (errno){ 86 perror_msg("File Writing/Saving failed: "); 87 unlink(filenamesfx); 88 } 89 free(filenamesfx); 90 } 91 92 void userdel_main(void) 93 { 94 struct passwd *pwd = NULL; 95 96 pwd = xgetpwnam(*toys.optargs); 97 update_password("/etc/passwd", pwd->pw_name, NULL); 98 update_password("/etc/shadow", pwd->pw_name, NULL); 99 100 // delete the group named USER, and remove user from group. 101 // could update_password() be used for this? 102 // not a good idea, as update_passwd() updates one entry at a time 103 // in this case it will be modifying the files as many times the 104 // USER appears in group database files. So the customized version 105 // of update_passwd() is here. 106 update_groupfiles("/etc/group", *toys.optargs); 107 update_groupfiles("/etc/gshadow", *toys.optargs); 108 109 if (toys.optflags & FLAG_r) { 110 char *arg[] = {"rm", "-fr", pwd->pw_dir, NULL, NULL}; 111 112 sprintf(toybuf, "/var/spool/mail/%s",pwd->pw_name); 113 arg[3] = toybuf; 114 xexec(arg); 115 } 116 } 117