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