diff options
Diffstat (limited to 'toys/pending/groupadd.c')
-rw-r--r-- | toys/pending/groupadd.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/toys/pending/groupadd.c b/toys/pending/groupadd.c new file mode 100644 index 00000000..ab290e54 --- /dev/null +++ b/toys/pending/groupadd.c @@ -0,0 +1,113 @@ +/* groupadd.c - create a new group + * + * Copyright 2013 Ashwini Kumar <ak.ashwini@gmail.com> + * Copyright 2013 Kyungwan Han <asura321@gmail.com> + * + * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/groupadd.html + +USE_GROUPADD(NEWTOY(groupadd, "<1>2g#<0S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) +USE_GROUPADD(OLDTOY(addgroup, groupadd, OPTSTR_groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) + +config GROUPADD + bool "groupadd" + default n + help + usage: groupadd [-S] [-g GID] [USER] GROUP + + Add a group or add a user to a group + + -g GID Group id + -S Create a system group +*/ + +#define FOR_groupadd +#include "toys.h" + +#define GROUP_PATH "/etc/group" +#define SECURE_GROUP_PATH "/etc/gshadow" + +GLOBALS( + long gid; +) + +/* Add a new group to the system, if GID is given then that is validated + * to be free, else a free GID is choosen by self. + * SYSTEM IDs are considered in the range 100 ... 999 + * update_group(), updates the entries in /etc/group, /etc/gshadow files + */ +static void new_group() +{ + char *entry = NULL; + int max = INT_MAX; + + if (toys.optflags & FLAG_g) { + if (TT.gid > INT_MAX) error_exit("gid should be less than '%d' ", INT_MAX); + if (getgrgid(TT.gid)) error_exit("group '%ld' is in use", TT.gid); + } else { + if (toys.optflags & FLAG_S) { + TT.gid = SYS_FIRST_ID; + max = SYS_LAST_ID; + } else { + TT.gid = SYS_LAST_ID + 1; //i.e. starting from 1000 + max = 60000; // as per config file on Linux desktop + } + //find unused gid + while (TT.gid <= max) { + if (!getgrgid(TT.gid)) break; + if (TT.gid == max) error_exit("no more free gids left"); + TT.gid++; + } + } + + entry = xmsprintf("%s:%s:%d:", *toys.optargs, "x", TT.gid); + update_password(GROUP_PATH, *toys.optargs, entry); + free(entry); + entry = xmsprintf("%s:%s::", *toys.optargs, "!"); + update_password(SECURE_GROUP_PATH, *toys.optargs, entry); + free(entry); +} + +void groupadd_main(void) +{ + struct group *grp = NULL; + char *entry = NULL; + + if (toys.optflags && toys.optc == 2) { + toys.exithelp = 1; + error_exit("options, user and group can't be together"); + } + + if (toys.optc == 2) { //add user to group + //toys.optargs[0]- user, toys.optargs[1] - group + if (!getpwnam(toys.optargs[0])) + error_exit("user '%s' does not exist", toys.optargs[0]); + if (!(grp = getgrnam(toys.optargs[1]))) + error_exit("group '%s' does not exist", toys.optargs[1]); + if (!grp->gr_mem) entry = xmsprintf("%s", *toys.optargs); + else { + int i; + + for (i = 0; grp->gr_mem[i]; i++) + if (!strcmp(grp->gr_mem[i], *toys.optargs)) return; + + entry = xstrdup(""); + for (i=0; grp->gr_mem[i]; i++) { + entry = xrealloc(entry, strlen(entry) + strlen(grp->gr_mem[i]) + 2); + strcat(entry, grp->gr_mem[i]); + strcat(entry, ","); + } + entry = xrealloc(entry, strlen(entry) + strlen(*toys.optargs) + 1); + strcat(entry, *toys.optargs); + } + update_password(GROUP_PATH, grp->gr_name, entry); + update_password(SECURE_GROUP_PATH, grp->gr_name, entry); + free(entry); + } else { //new group to be created + /* investigate the group to be created */ + if ((grp = getgrnam(*toys.optargs))) + error_exit("group '%s' is in use", *toys.optargs); + setlocale(LC_ALL, "C"); + is_valid_username(*toys.optargs); + new_group(); + } +} |