groupadd.c revision 59d85e2bb065a3bdc27868acb7a65f89d872c7fa
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
8USE_GROUPADD(NEWTOY(groupadd, "<1>2g#<0S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
9USE_GROUPADD(OLDTOY(addgroup, groupadd, OPTSTR_groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
10
11config 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
29GLOBALS(
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 */
38static void new_group()
39{
40  char *entry = NULL;
41  int max = INT_MAX;
42
43  if (toys.optflags & FLAG_g) {
44    if (TT.gid > INT_MAX) error_exit("gid should be less than  '%d' ", INT_MAX);
45    if (getgrgid(TT.gid)) error_exit("group '%ld' is in use", TT.gid);
46  } else {
47    if (toys.optflags & FLAG_S) {
48      TT.gid = SYS_FIRST_ID;
49      max = SYS_LAST_ID;
50    } else {
51      TT.gid = SYS_LAST_ID + 1; //i.e. starting from 1000
52      max = 60000; // as per config file on Linux desktop
53    }
54    //find unused gid
55    while (TT.gid <= max) {
56      if (!getgrgid(TT.gid)) break;
57      if (TT.gid == max) error_exit("no more free gids left");
58      TT.gid++;
59    }
60  }
61
62  entry = xmprintf("%s:%s:%d:", *toys.optargs, "x", TT.gid);
63  update_password(GROUP_PATH, *toys.optargs, entry);
64  free(entry);
65  entry = xmprintf("%s:%s::", *toys.optargs, "!");
66  update_password(SECURE_GROUP_PATH, *toys.optargs, entry);
67  free(entry);
68}
69
70void groupadd_main(void)
71{
72  struct group *grp = NULL;
73  char *entry = NULL;
74
75  if (toys.optflags && toys.optc == 2) {
76    toys.exithelp = 1;
77    error_exit("options, user and group can't be together");
78  }
79
80  if (toys.optc == 2) {  //add user to group
81    //toys.optargs[0]- user, toys.optargs[1] - group
82    xgetpwnam(*toys.optargs);
83    if (!(grp = getgrnam(toys.optargs[1])))
84      error_exit("group '%s' does not exist", toys.optargs[1]);
85    if (!grp->gr_mem) entry = xmprintf("%s", *toys.optargs);
86    else {
87      int i;
88
89      for (i = 0; grp->gr_mem[i]; i++)
90        if (!strcmp(grp->gr_mem[i], *toys.optargs)) return;
91
92      entry = xstrdup("");
93      for (i=0; grp->gr_mem[i]; i++) {
94        entry = xrealloc(entry, strlen(entry) + strlen(grp->gr_mem[i]) + 2);
95        strcat(entry, grp->gr_mem[i]);
96        strcat(entry, ",");
97      }
98      entry = xrealloc(entry, strlen(entry) + strlen(*toys.optargs) + 1);
99      strcat(entry, *toys.optargs);
100    }
101    update_password(GROUP_PATH, grp->gr_name, entry);
102    update_password(SECURE_GROUP_PATH, grp->gr_name, entry);
103    free(entry);
104  } else {    //new group to be created
105    /* investigate the group to be created */
106    if ((grp = getgrnam(*toys.optargs)))
107      error_exit("group '%s' is in use", *toys.optargs);
108    setlocale(LC_ALL, "C");
109    is_valid_username(*toys.optargs);
110    new_group();
111  }
112}
113