1 /* groupadd.c - create a new group
2  *
3  * Copyright 2013 Ashwini Kumar <ak.ashwini@gmail.com>
4  * Copyright 2013 Kyungwan Han <asura321@gmail.com>
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>2g#<0S", 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 group or add a user to a group
18 
19       -g GID Group id
20       -S     Create a system group
21 */
22 
23 #define FOR_groupadd
24 #include "toys.h"
25 
26 #define GROUP_PATH        "/etc/group"
27 #define SECURE_GROUP_PATH "/etc/gshadow"
28 
GLOBALS(long gid;)29 GLOBALS(
30   long gid;
31 )
32 
33 /* Add a new group to the system, if GID is given then that is validated
34  * to be free, else a free GID is choosen by self.
35  * SYSTEM IDs are considered in the range 100 ... 999
36  * update_group(), updates the entries in /etc/group, /etc/gshadow files
37  */
38 static void new_group()
39 {
40   char *entry = NULL;
41 
42   if (toys.optflags & FLAG_g) {
43     if (TT.gid > INT_MAX) error_exit("gid should be less than  '%d' ", INT_MAX);
44     if (getgrgid(TT.gid)) error_exit("group '%ld' is in use", TT.gid);
45   } else {
46     if (toys.optflags & FLAG_S) TT.gid = CFG_TOYBOX_UID_SYS;
47     else TT.gid = CFG_TOYBOX_UID_USR;
48     //find unused gid
49     while (getgrgid(TT.gid)) TT.gid++;
50   }
51 
52   entry = xmprintf("%s:%s:%d:", *toys.optargs, "x", TT.gid);
53   update_password(GROUP_PATH, *toys.optargs, entry);
54   free(entry);
55   entry = xmprintf("%s:%s::", *toys.optargs, "!");
56   update_password(SECURE_GROUP_PATH, *toys.optargs, entry);
57   free(entry);
58 }
59 
groupadd_main(void)60 void groupadd_main(void)
61 {
62   struct group *grp = NULL;
63   char *entry = NULL;
64 
65   if (toys.optflags && toys.optc == 2) {
66     toys.exithelp = 1;
67     error_exit("options, user and group can't be together");
68   }
69 
70   if (toys.optc == 2) {  //add user to group
71     //toys.optargs[0]- user, toys.optargs[1] - group
72     xgetpwnam(*toys.optargs);
73     if (!(grp = getgrnam(toys.optargs[1])))
74       error_exit("group '%s' does not exist", toys.optargs[1]);
75     if (!grp->gr_mem) entry = xmprintf("%s", *toys.optargs);
76     else {
77       int i;
78 
79       for (i = 0; grp->gr_mem[i]; i++)
80         if (!strcmp(grp->gr_mem[i], *toys.optargs)) return;
81 
82       entry = xstrdup("");
83       for (i=0; grp->gr_mem[i]; i++) {
84         entry = xrealloc(entry, strlen(entry) + strlen(grp->gr_mem[i]) + 2);
85         strcat(entry, grp->gr_mem[i]);
86         strcat(entry, ",");
87       }
88       entry = xrealloc(entry, strlen(entry) + strlen(*toys.optargs) + 1);
89       strcat(entry, *toys.optargs);
90     }
91     update_password(GROUP_PATH, grp->gr_name, entry);
92     update_password(SECURE_GROUP_PATH, grp->gr_name, entry);
93     free(entry);
94   } else {    //new group to be created
95     char *s = *toys.optargs;
96 
97     /* investigate the group to be created */
98     if (getgrnam(s)) error_exit("'%s' in use", s);
99     if (s[strcspn(s, ":/\n")] || strlen(s) > LOGIN_NAME_MAX)
100       error_exit("bad name");
101     new_group();
102   }
103 }
104