1/* vi: set sw=4 ts=4: */ 2/* 3 * deluser/delgroup implementation for busybox 4 * 5 * Copyright (C) 1999 by Lineo, inc. and John Beppu 6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> 7 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it> 8 * 9 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 10 * 11 */ 12 13#include "libbb.h" 14 15/* Status */ 16#define STATUS_OK 0 17#define NAME_NOT_FOUND 1 18#define MEMBER_NOT_FOUND 2 19 20static void del_line_matching(char **args, 21 const char *filename, 22 FILE *(*fopen_func)(const char *fileName, const char *mode)) 23{ 24 FILE *passwd; 25 smallint error = NAME_NOT_FOUND; 26 char *name = (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) ? args[2] : args[1]; 27 char *line, *del; 28 char *new = xzalloc(1); 29 30 passwd = fopen_func(filename, "r"); 31 if (passwd) { 32 while ((line = xmalloc_fgets(passwd))) { 33 int len = strlen(name); 34 35 if (strncmp(line, name, len) == 0 36 && line[len] == ':' 37 ) { 38 error = STATUS_OK; 39 if (ENABLE_FEATURE_DEL_USER_FROM_GROUP) { 40 struct group *gr; 41 char *p; 42 if (args[2] 43 /* There were two args on commandline */ 44 && (gr = getgrnam(name)) 45 /* The group was not deleted in the meanwhile */ 46 && (p = strrchr(line, ':')) 47 /* We can find a pointer to the last ':' */ 48 ) { 49 error = MEMBER_NOT_FOUND; 50 /* Move past ':' (worst case to '\0') and cut the line */ 51 p[1] = '\0'; 52 /* Reuse p */ 53 for (p = xzalloc(1); *gr->gr_mem != NULL; gr->gr_mem++) { 54 /* Add all the other group members */ 55 if (strcmp(args[1], *gr->gr_mem) != 0) { 56 del = p; 57 p = xasprintf("%s%s%s", p, p[0] ? "," : "", *gr->gr_mem); 58 free(del); 59 } else 60 error = STATUS_OK; 61 } 62 /* Recompose the line */ 63 line = xasprintf("%s%s\n", line, p); 64 if (ENABLE_FEATURE_CLEAN_UP) free(p); 65 } else 66 goto skip; 67 } 68 } 69 del = new; 70 new = xasprintf("%s%s", new, line); 71 free(del); 72 skip: 73 free(line); 74 } 75 76 if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd); 77 78 if (error) { 79 if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && error == MEMBER_NOT_FOUND) { 80 /* Set the correct values for error message */ 81 filename = name; 82 name = args[1]; 83 } 84 bb_error_msg("can't find %s in %s", name, filename); 85 } else { 86 passwd = fopen_func(filename, "w"); 87 if (passwd) { 88 fputs(new, passwd); 89 if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd); 90 } 91 } 92 } 93 free(new); 94} 95 96int deluser_main(int argc, char **argv); 97int deluser_main(int argc, char **argv) 98{ 99 if (argc == 2 100 || (ENABLE_FEATURE_DEL_USER_FROM_GROUP 101 && (applet_name[3] == 'g' && argc == 3)) 102 ) { 103 if (geteuid()) 104 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); 105 106 if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3) 107 || ENABLE_DELUSER 108 || (ENABLE_DELGROUP && ENABLE_DESKTOP) 109 ) { 110 if (ENABLE_DELUSER 111 && (!ENABLE_DELGROUP || applet_name[3] == 'u') 112 ) { 113 del_line_matching(argv, bb_path_passwd_file, xfopen); 114 if (ENABLE_FEATURE_SHADOWPASSWDS) 115 del_line_matching(argv, bb_path_shadow_file, fopen_or_warn); 116 } else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1])) 117 bb_error_msg_and_die("can't remove primary group of user %s", argv[1]); 118 } 119 del_line_matching(argv, bb_path_group_file, xfopen); 120 if (ENABLE_FEATURE_SHADOWPASSWDS) 121 del_line_matching(argv, bb_path_gshadow_file, fopen_or_warn); 122 return EXIT_SUCCESS; 123 } else 124 bb_show_usage(); 125} 126