X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=loginutils%2Faddgroup.c;h=b25f8171df7416f2baacf03052b5aa7740b0644d;hb=403a5a298eaa5d1d827ad6ebbf38a7b765ba5b44;hp=78250a4180b7cd227b09958590e82b92300982e1;hpb=5df955fce2fbdc5b2acc365a120327ff943403da;p=oweals%2Fbusybox.git diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 78250a418..b25f8171d 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -1,58 +1,49 @@ /* vi: set sw=4 ts=4: */ /* - * addgroup - add users to /etc/passwd and /etc/shadow + * addgroup - add groups to /etc/group and /etc/gshadow * * Copyright (C) 1999 by Lineo, inc. and John Beppu * Copyright (C) 1999,2000,2001 by John Beppu + * Copyright (C) 2007 by Tito Ragusa * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * */ -#include "busybox.h" +#include "libbb.h" -/* make sure gr_name isn't taken, make sure gid is kosher - * return 1 on failure */ -static int group_study(struct group *g) +static void xgroup_study(struct group *g) { - enum { max = 65000 }; - FILE *etc_group; - gid_t desired; - /* Using _r function to avoid static buffers pulled in */ - char buffer[256]; - struct group grp; - struct group *result; - - etc_group = xfopen(bb_path_group_file, "r"); - - /* make sure gr_name isn't taken, make sure gid is kosher */ - desired = g->gr_gid; - while (!fgetgrent_r(etc_group, &grp, buffer, sizeof(buffer), &result)) { - if ((strcmp(grp.gr_name, g->gr_name)) == 0) { - bb_error_msg_and_die("%s: group already in use", g->gr_name); + /* Make sure gr_name is unused */ + if (getgrnam(g->gr_name)) { + goto error; + } + + /* Check if the desired gid is free + * or find the first free one */ + while (1) { + if (!getgrgid(g->gr_gid)) { + return; /* found free group: return */ } - if ((desired) && grp.gr_gid == desired) { - bb_error_msg_and_die("%d: gid already in use", - desired); + if (option_mask32) { + /* -g N, cannot pick gid other than N: error */ + g->gr_name = itoa(g->gr_gid); + goto error; } - if ((grp.gr_gid > g->gr_gid) && (grp.gr_gid < max)) { - g->gr_gid = grp.gr_gid; + g->gr_gid++; + if (g->gr_gid <= 0) { + /* overflowed: error */ + bb_error_msg_and_die("no gids left"); } } - if (ENABLE_FEATURE_CLEAN_UP) - fclose(etc_group); - /* gid */ - g->gr_gid++; - if (desired) { - g->gr_gid = desired; - } - /* return 1; */ - return 0; + error: + /* exit */ + bb_error_msg_and_die("group %s already exists", g->gr_name); } /* append a new user to the passwd file */ -static int addgroup(char *group, gid_t gid, const char *user) +static void new_group(char *group, gid_t gid) { FILE *file; struct group gr; @@ -60,16 +51,14 @@ static int addgroup(char *group, gid_t gid, const char *user) /* make sure gid and group haven't already been allocated */ gr.gr_gid = gid; gr.gr_name = group; - if (group_study(&gr)) - return 1; + xgroup_study(&gr); /* add entry to group */ file = xfopen(bb_path_group_file, "a"); /* group:passwd:gid:userlist */ - fprintf(file, "%s:%s:%d:%s\n", group, "x", gr.gr_gid, user); + fprintf(file, "%s:x:%u:\n", group, (unsigned)gr.gr_gid); if (ENABLE_FEATURE_CLEAN_UP) fclose(file); - #if ENABLE_FEATURE_SHADOWPASSWDS file = fopen_or_warn(bb_path_gshadow_file, "a"); if (file) { @@ -78,34 +67,114 @@ static int addgroup(char *group, gid_t gid, const char *user) fclose(file); } #endif +} + +#if ENABLE_FEATURE_ADDUSER_TO_GROUP +static void add_user_to_group(char **args, + const char *path, + FILE *(*fopen_func)(const char *fileName, const char *mode)) +{ + char *line; + int len = strlen(args[1]); + llist_t *plist = NULL; + FILE *group_file; - /* return 1; */ - return 0; + group_file = fopen_func(path, "r"); + + if (!group_file) return; + + while ((line = xmalloc_getline(group_file))) { + /* Find the group */ + if (!strncmp(line, args[1], len) + && line[len] == ':' + ) { + /* Add the new user */ + line = xasprintf("%s%s%s", line, + last_char_is(line, ':') ? "" : ",", + args[0]); + } + llist_add_to_end(&plist, line); + } + + if (ENABLE_FEATURE_CLEAN_UP) { + fclose(group_file); + group_file = fopen_func(path, "w"); + while ((line = llist_pop(&plist))) { + if (group_file) + fprintf(group_file, "%s\n", line); + free(line); + } + if (group_file) + fclose(group_file); + } else { + group_file = fopen_func(path, "w"); + if (group_file) + while ((line = llist_pop(&plist))) + fprintf(group_file, "%s\n", line); + } } +#endif /* * addgroup will take a login_name as its first parameter. * * gid can be customized via command-line parameters. + * If called with two non-option arguments, addgroup + * will add an existing user to an existing group. */ -int addgroup_main(int argc, char **argv); -int addgroup_main(int argc, char **argv) +int addgroup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int addgroup_main(int argc ATTRIBUTE_UNUSED, char **argv) { char *group; gid_t gid = 0; - /* check for min, max and missing args and exit on error */ - opt_complementary = "-1:?2:?"; - if (getopt32(argc, argv, "g:", &group)) { - gid = xatoul_range(group, 0, (gid_t)ULONG_MAX); - } - /* move past the commandline options */ - argv += optind; - /* need to be root */ if (geteuid()) { bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); } - return addgroup(argv[0], gid, argv[1] ? argv[1] : ""); + /* Syntax: + * addgroup group + * addgroup -g num group + * addgroup user group + * Check for min, max and missing args */ + opt_complementary = "-1:?2"; + if (getopt32(argv, "g:", &group)) { + gid = xatoul_range(group, 0, ((unsigned long)(gid_t)ULONG_MAX) >> 1); + } + /* move past the commandline options */ + argv += optind; + //argc -= optind; + +#if ENABLE_FEATURE_ADDUSER_TO_GROUP + if (argv[1]) { + struct group *gr; + + if (option_mask32) { + /* -g was there, but "addgroup -g num user group" + * is a no-no */ + bb_show_usage(); + } + + /* check if group and user exist */ + xuname2uid(argv[0]); /* unknown user: exit */ + xgroup2gid(argv[1]); /* unknown group: exit */ + /* check if user is already in this group */ + gr = getgrnam(argv[1]); + for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) { + if (!strcmp(argv[0], *(gr->gr_mem))) { + /* user is already in group: do nothing */ + return EXIT_SUCCESS; + } + } + add_user_to_group(argv, bb_path_group_file, xfopen); +#if ENABLE_FEATURE_SHADOWPASSWDS + add_user_to_group(argv, bb_path_gshadow_file, fopen_or_warn); +#endif + } else +#endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */ + new_group(argv[0], gid); + + /* Reached only on success */ + return EXIT_SUCCESS; }