10f66f451Sopenharmony_ci/* userdel.c - delete a user 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2014 Ashwini Kumar <ak.ashwini1981@gmail.com> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/userdel.html 60f66f451Sopenharmony_ci 70f66f451Sopenharmony_ciUSE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 80f66f451Sopenharmony_ciUSE_USERDEL(OLDTOY(deluser, userdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciconfig USERDEL 110f66f451Sopenharmony_ci bool "userdel" 120f66f451Sopenharmony_ci default n 130f66f451Sopenharmony_ci help 140f66f451Sopenharmony_ci usage: userdel [-r] USER 150f66f451Sopenharmony_ci usage: deluser [-r] USER 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci Delete USER from the SYSTEM 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci -r remove home directory 200f66f451Sopenharmony_ci*/ 210f66f451Sopenharmony_ci 220f66f451Sopenharmony_ci#define FOR_userdel 230f66f451Sopenharmony_ci#include "toys.h" 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_cistatic void update_groupfiles(char *filename, char* username) 260f66f451Sopenharmony_ci{ 270f66f451Sopenharmony_ci char *filenamesfx = NULL, *sfx = NULL, *line = NULL; 280f66f451Sopenharmony_ci FILE *exfp, *newfp; 290f66f451Sopenharmony_ci int ulen = strlen(username); 300f66f451Sopenharmony_ci size_t allocated_length = 0; 310f66f451Sopenharmony_ci struct flock lock; 320f66f451Sopenharmony_ci 330f66f451Sopenharmony_ci filenamesfx = xmprintf("%s+", filename); 340f66f451Sopenharmony_ci sfx = strchr(filenamesfx, '+'); 350f66f451Sopenharmony_ci exfp = xfopen(filename, "r+"); 360f66f451Sopenharmony_ci 370f66f451Sopenharmony_ci *sfx = '-'; 380f66f451Sopenharmony_ci unlink(filenamesfx); 390f66f451Sopenharmony_ci if (link(filename, filenamesfx)) error_msg("Can't create backup file"); 400f66f451Sopenharmony_ci 410f66f451Sopenharmony_ci *sfx = '+'; 420f66f451Sopenharmony_ci lock.l_type = F_WRLCK; 430f66f451Sopenharmony_ci lock.l_whence = SEEK_SET; 440f66f451Sopenharmony_ci lock.l_start = lock.l_len = 0; 450f66f451Sopenharmony_ci 460f66f451Sopenharmony_ci if (fcntl(fileno(exfp), F_SETLK, &lock) < 0) 470f66f451Sopenharmony_ci perror_msg("Couldn't lock file %s",filename); 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_ci lock.l_type = F_UNLCK; //unlocking at a later stage 500f66f451Sopenharmony_ci 510f66f451Sopenharmony_ci newfp = xfopen(filenamesfx, "w+"); 520f66f451Sopenharmony_ci 530f66f451Sopenharmony_ci while (getline(&line, &allocated_length, exfp) > 0) { 540f66f451Sopenharmony_ci sprintf(toybuf, "%s:",username); 550f66f451Sopenharmony_ci if (strncmp(line, toybuf, ulen+1)) { 560f66f451Sopenharmony_ci char *n, *p = strrchr(line, ':'); 570f66f451Sopenharmony_ci 580f66f451Sopenharmony_ci if (p && *++p && (n = strstr(p, username))) { 590f66f451Sopenharmony_ci do { 600f66f451Sopenharmony_ci if (n[ulen] == ',') { 610f66f451Sopenharmony_ci *n = '\0'; 620f66f451Sopenharmony_ci n += ulen + 1; 630f66f451Sopenharmony_ci fprintf(newfp, "%s%s\n", line, n); 640f66f451Sopenharmony_ci break; 650f66f451Sopenharmony_ci } else if (!n[ulen]) { 660f66f451Sopenharmony_ci if (n[-1] == ',') n[-1] = *n = '\0'; 670f66f451Sopenharmony_ci if (n[-1] == ':') *n = '\0'; 680f66f451Sopenharmony_ci fprintf(newfp, "%s%s\n", line, n); 690f66f451Sopenharmony_ci break; 700f66f451Sopenharmony_ci } else n += ulen; 710f66f451Sopenharmony_ci } while (*n && (n=strstr(n, username))); 720f66f451Sopenharmony_ci if (!n) fprintf(newfp, "%s\n", line); 730f66f451Sopenharmony_ci } else fprintf(newfp, "%s\n", line); 740f66f451Sopenharmony_ci } 750f66f451Sopenharmony_ci } 760f66f451Sopenharmony_ci free(line); 770f66f451Sopenharmony_ci fcntl(fileno(exfp), F_SETLK, &lock); 780f66f451Sopenharmony_ci fclose(exfp); 790f66f451Sopenharmony_ci errno = 0; 800f66f451Sopenharmony_ci fflush(newfp); 810f66f451Sopenharmony_ci fsync(fileno(newfp)); 820f66f451Sopenharmony_ci fclose(newfp); 830f66f451Sopenharmony_ci rename(filenamesfx, filename); 840f66f451Sopenharmony_ci if (errno){ 850f66f451Sopenharmony_ci perror_msg("File Writing/Saving failed: "); 860f66f451Sopenharmony_ci unlink(filenamesfx); 870f66f451Sopenharmony_ci } 880f66f451Sopenharmony_ci free(filenamesfx); 890f66f451Sopenharmony_ci} 900f66f451Sopenharmony_ci 910f66f451Sopenharmony_civoid userdel_main(void) 920f66f451Sopenharmony_ci{ 930f66f451Sopenharmony_ci struct passwd *pwd = xgetpwnam(*toys.optargs); 940f66f451Sopenharmony_ci 950f66f451Sopenharmony_ci update_password("/etc/passwd", pwd->pw_name, NULL); 960f66f451Sopenharmony_ci update_password("/etc/shadow", pwd->pw_name, NULL); 970f66f451Sopenharmony_ci 980f66f451Sopenharmony_ci // delete the group named USER, and remove user from group. 990f66f451Sopenharmony_ci // could update_password() be used for this? 1000f66f451Sopenharmony_ci // not a good idea, as update_passwd() updates one entry at a time 1010f66f451Sopenharmony_ci // in this case it will be modifying the files as many times the 1020f66f451Sopenharmony_ci // USER appears in group database files. So the customized version 1030f66f451Sopenharmony_ci // of update_passwd() is here. 1040f66f451Sopenharmony_ci update_groupfiles("/etc/group", *toys.optargs); 1050f66f451Sopenharmony_ci update_groupfiles("/etc/gshadow", *toys.optargs); 1060f66f451Sopenharmony_ci 1070f66f451Sopenharmony_ci if (FLAG(r)) { 1080f66f451Sopenharmony_ci char *arg[] = {"rm", "-fr", pwd->pw_dir, NULL, NULL}; 1090f66f451Sopenharmony_ci 1100f66f451Sopenharmony_ci sprintf(toybuf, "/var/spool/mail/%s",pwd->pw_name); 1110f66f451Sopenharmony_ci arg[3] = toybuf; 1120f66f451Sopenharmony_ci xexec(arg); 1130f66f451Sopenharmony_ci } 1140f66f451Sopenharmony_ci} 115