• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
update_groupfiles(char * filename,char * username)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   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 
userdel_main(void)91 void 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