1*cf5a6c84SAndroid Build Coastguard Worker /* groupadd.c - create a new group
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Ashwini Kumar <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker *
6*cf5a6c84SAndroid Build Coastguard Worker * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/groupadd.html
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker USE_GROUPADD(NEWTOY(groupadd, "<1>2R:g#<0>2147483647S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
9*cf5a6c84SAndroid Build Coastguard Worker USE_GROUPADD(OLDTOY(addgroup, groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
10*cf5a6c84SAndroid Build Coastguard Worker
11*cf5a6c84SAndroid Build Coastguard Worker config GROUPADD
12*cf5a6c84SAndroid Build Coastguard Worker bool "groupadd"
13*cf5a6c84SAndroid Build Coastguard Worker default n
14*cf5a6c84SAndroid Build Coastguard Worker help
15*cf5a6c84SAndroid Build Coastguard Worker usage: groupadd [-S] [-g GID] [USER] GROUP
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker Add a user to a group, or create a new group.
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker -g GID Group id
20*cf5a6c84SAndroid Build Coastguard Worker -R Operate within chroot
21*cf5a6c84SAndroid Build Coastguard Worker -S Create a system group
22*cf5a6c84SAndroid Build Coastguard Worker */
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker #define FOR_groupadd
25*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
26*cf5a6c84SAndroid Build Coastguard Worker
GLOBALS(long g;char * R;)27*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
28*cf5a6c84SAndroid Build Coastguard Worker long g;
29*cf5a6c84SAndroid Build Coastguard Worker char *R;
30*cf5a6c84SAndroid Build Coastguard Worker )
31*cf5a6c84SAndroid Build Coastguard Worker
32*cf5a6c84SAndroid Build Coastguard Worker /* Add a new group to the system, if GID is given then that is validated
33*cf5a6c84SAndroid Build Coastguard Worker * to be free, else a free GID is choosen by self.
34*cf5a6c84SAndroid Build Coastguard Worker * SYSTEM IDs are considered in the range 100 ... 999
35*cf5a6c84SAndroid Build Coastguard Worker * update_group(), updates the entries in /etc/group, /etc/gshadow files
36*cf5a6c84SAndroid Build Coastguard Worker */
37*cf5a6c84SAndroid Build Coastguard Worker
38*cf5a6c84SAndroid Build Coastguard Worker void groupadd_main(void)
39*cf5a6c84SAndroid Build Coastguard Worker {
40*cf5a6c84SAndroid Build Coastguard Worker struct group *grp = 0;
41*cf5a6c84SAndroid Build Coastguard Worker char *entry = 0, *s, *gfile = "/etc/group", *gsfile = "/etc/gshadow";
42*cf5a6c84SAndroid Build Coastguard Worker int i, len;
43*cf5a6c84SAndroid Build Coastguard Worker
44*cf5a6c84SAndroid Build Coastguard Worker if (TT.R) {
45*cf5a6c84SAndroid Build Coastguard Worker gfile = xmprintf("%s%s", TT.R, gfile);
46*cf5a6c84SAndroid Build Coastguard Worker gsfile = xmprintf("%s%s", TT.R, gsfile);
47*cf5a6c84SAndroid Build Coastguard Worker }
48*cf5a6c84SAndroid Build Coastguard Worker
49*cf5a6c84SAndroid Build Coastguard Worker // Add user to group?
50*cf5a6c84SAndroid Build Coastguard Worker if (toys.optc == 2) {
51*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(g)|FLAG(S)) help_exit("No -gS with USER+GROUP");
52*cf5a6c84SAndroid Build Coastguard Worker if (!(grp = getgrnam(s = toys.optargs[1]))) error_exit("no group '%s'", s);
53*cf5a6c84SAndroid Build Coastguard Worker len = strlen(s)+1;
54*cf5a6c84SAndroid Build Coastguard Worker xgetpwnam(s = *toys.optargs);
55*cf5a6c84SAndroid Build Coastguard Worker
56*cf5a6c84SAndroid Build Coastguard Worker // Is this user already in this group?
57*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; grp->gr_mem[i]; i++) {
58*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(grp->gr_mem[i], s)) return;
59*cf5a6c84SAndroid Build Coastguard Worker len += strlen(grp->gr_mem[i])+1;
60*cf5a6c84SAndroid Build Coastguard Worker }
61*cf5a6c84SAndroid Build Coastguard Worker s = entry = xmalloc(len);
62*cf5a6c84SAndroid Build Coastguard Worker for (i = 0;; i++) {
63*cf5a6c84SAndroid Build Coastguard Worker if (i) *s++ = ',';
64*cf5a6c84SAndroid Build Coastguard Worker if (!grp->gr_mem[i]) {
65*cf5a6c84SAndroid Build Coastguard Worker strcpy(s, toys.optargs[1]);
66*cf5a6c84SAndroid Build Coastguard Worker break;
67*cf5a6c84SAndroid Build Coastguard Worker }
68*cf5a6c84SAndroid Build Coastguard Worker s = stpcpy(s, grp->gr_mem[i]);
69*cf5a6c84SAndroid Build Coastguard Worker }
70*cf5a6c84SAndroid Build Coastguard Worker update_password(gfile, grp->gr_name, entry, 3);
71*cf5a6c84SAndroid Build Coastguard Worker update_password(gsfile, grp->gr_name, entry, 3);
72*cf5a6c84SAndroid Build Coastguard Worker free(entry);
73*cf5a6c84SAndroid Build Coastguard Worker
74*cf5a6c84SAndroid Build Coastguard Worker return;
75*cf5a6c84SAndroid Build Coastguard Worker }
76*cf5a6c84SAndroid Build Coastguard Worker
77*cf5a6c84SAndroid Build Coastguard Worker // create new group
78*cf5a6c84SAndroid Build Coastguard Worker if (getgrnam(s = *toys.optargs)) error_exit("'%s' in use", s);
79*cf5a6c84SAndroid Build Coastguard Worker if (s[strcspn(s, ":/\n")] || strlen(s)>256) error_exit("bad '%s'", s);
80*cf5a6c84SAndroid Build Coastguard Worker
81*cf5a6c84SAndroid Build Coastguard Worker // Find next unused GID or confirm selected GID isn't in use
82*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(g)) {
83*cf5a6c84SAndroid Build Coastguard Worker TT.g = FLAG(S) ? CFG_TOYBOX_UID_SYS : CFG_TOYBOX_UID_USR;
84*cf5a6c84SAndroid Build Coastguard Worker while (getgrgid(TT.g)) TT.g++;
85*cf5a6c84SAndroid Build Coastguard Worker } else if (getgrgid(TT.g)) error_exit("group '%ld' in use", TT.g);
86*cf5a6c84SAndroid Build Coastguard Worker
87*cf5a6c84SAndroid Build Coastguard Worker sprintf(toybuf, "%s:x:%ld:", s, TT.g);
88*cf5a6c84SAndroid Build Coastguard Worker update_password(gfile, s, toybuf, 0);
89*cf5a6c84SAndroid Build Coastguard Worker sprintf(toybuf, "%s:!::", s);
90*cf5a6c84SAndroid Build Coastguard Worker update_password(gsfile, s, toybuf, 0);
91*cf5a6c84SAndroid Build Coastguard Worker }
92