Home | History | Annotate | Download | only in pending
      1 /* userdel.c - delete a user
      2  *
      3  * Copyright 2014 Ashwini Kumar <ak.ashwini1981 (at) 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     Options:
     18     -r remove home directory
     19     Delete USER from the SYSTEM
     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