userdel.c 3.1 KB

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