add usefun info on SIGINT handling peculiarities
[oweals/busybox.git] / loginutils / addgroup.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * addgroup - add users to /etc/passwd and /etc/shadow
4  *
5  * Copyright (C) 1999 by Lineo, inc. and John Beppu
6  * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7  *
8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9  *
10  */
11
12 #include "busybox.h"
13
14 /* make sure gr_name isn't taken, make sure gid is kosher
15  * return 1 on failure */
16 static int group_study(struct group *g)
17 {
18         FILE *etc_group;
19         gid_t desired;
20
21         struct group *grp;
22         const int max = 65000;
23
24         etc_group = xfopen(bb_path_group_file, "r");
25
26         /* make sure gr_name isn't taken, make sure gid is kosher */
27         desired = g->gr_gid;
28         while ((grp = fgetgrent(etc_group))) {
29                 if ((strcmp(grp->gr_name, g->gr_name)) == 0) {
30                         bb_error_msg_and_die("%s: group already in use", g->gr_name);
31                 }
32                 if ((desired) && grp->gr_gid == desired) {
33                         bb_error_msg_and_die("%d: gid already in use",
34                                                           desired);
35                 }
36                 if ((grp->gr_gid > g->gr_gid) && (grp->gr_gid < max)) {
37                         g->gr_gid = grp->gr_gid;
38                 }
39         }
40         fclose(etc_group);
41
42         /* gid */
43         if (desired) {
44                 g->gr_gid = desired;
45         } else {
46                 g->gr_gid++;
47         }
48         /* return 1; */
49         return 0;
50 }
51
52 /* append a new user to the passwd file */
53 static int addgroup(char *group, gid_t gid, const char *user)
54 {
55         FILE *file;
56         struct group gr;
57
58         /* make sure gid and group haven't already been allocated */
59         gr.gr_gid = gid;
60         gr.gr_name = group;
61         if (group_study(&gr))
62                 return 1;
63
64         /* add entry to group */
65         file = xfopen(bb_path_group_file, "a");
66         /* group:passwd:gid:userlist */
67         fprintf(file, "%s:%s:%d:%s\n", group, "x", gr.gr_gid, user);
68         fclose(file);
69
70 #if ENABLE_FEATURE_SHADOWPASSWDS
71         file = xfopen(bb_path_gshadow_file, "a");
72         fprintf(file, "%s:!::\n", group);
73         fclose(file);
74 #endif
75
76         /* return 1; */
77         return 0;
78 }
79
80 /*
81  * addgroup will take a login_name as its first parameter.
82  *
83  * gid
84  *
85  * can be customized via command-line parameters.
86  * ________________________________________________________________________ */
87 int addgroup_main(int argc, char **argv)
88 {
89         char *group;
90         gid_t gid = 0;
91
92         /* check for min, max and missing args and exit on error */
93         opt_complementary = "-1:?2:?";
94         if (getopt32(argc, argv, "g:", &group)) {
95                 gid = xatoul_range(group, 0, (gid_t)ULONG_MAX);
96         }
97         /* move past the commandline options */
98         argv += optind;
99
100         /* need to be root */
101         if (geteuid()) {
102                 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
103         }
104
105         /* werk */
106         return addgroup(argv[0], gid, (argv[1]) ? argv[1] : "");
107 }