xref: /third_party/toybox/toys/pending/userdel.c (revision 0f66f451)
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