blob: 3d932011c1fe0055025707944600f8e6c9241550 [file] [log] [blame]
Eric Andersenf349e972001-08-21 16:18:59 +00001/* vi: set sw=4 ts=4: */
2/*
3 * addgroup - add users to /etc/passwd and /etc/shadow
4 *
5 *
6 * Copyright (C) 1999 by Lineo, inc.
7 * Written by John Beppu <beppu@lineo.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include <errno.h>
26#include <fcntl.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <unistd.h>
35#include "busybox.h"
36#include "pwd_grp/pwd.h"
37#include "pwd_grp/grp.h"
38
39#define GROUP_FILE "/etc/group"
40#define SHADOW_FILE "/etc/gshadow"
41
42
43/* structs __________________________ */
44
45/* data _____________________________ */
46
47/* defaults : should this be in an external file? */
48static char *default_passwd = "x";
49
50
51/* make sure gr_name isn't taken, make sure gid is kosher
52 * return 1 on failure */
53static int group_study(const char *filename, struct group *g)
54{
55 FILE *etc_group;
56 gid_t desired;
57
58 struct group *grp;
59 const int max = 65000;
60
61 /* FIXME : make an fopen_wrapper */
62 etc_group = fopen(filename, "r");
63 if (!etc_group) {
64 perror_msg_and_die("%s", filename);
65 }
66
67 /* make sure gr_name isn't taken, make sure gid is kosher */
68 desired = g->gr_gid;
69 while ((grp = fgetgrent(etc_group))) {
70 if ((strcmp(grp->gr_name, g->gr_name)) == 0) {
71 error_msg_and_die("%s: group already in use\n", g->gr_name);
72 }
73 if ((desired) && grp->gr_gid == desired) {
74 error_msg_and_die("%d: gid has already been allocated\n",
75 desired);
76 }
77 if ((grp->gr_gid > g->gr_gid) && (grp->gr_gid < max)) {
78 g->gr_gid = grp->gr_gid;
79 }
80 }
81 fclose(etc_group);
82
83 /* gid */
84 if (desired) {
85 g->gr_gid = desired;
86 } else {
87 g->gr_gid++;
88 }
89 /* return 1; */
90 return 0;
91}
92
93/* append a new user to the passwd file */
94static int addgroup(const char *filename, char *group, gid_t gid)
95{
96 FILE *etc_group;
97 FILE *etc_gshadow;
98 char *gshadow = SHADOW_FILE;
99
100 struct group gr;
101
102 /* group:passwd:gid:userlist */
103 const char *entryfmt = "%s:%s:%d:%s\n";
104
105 /* make sure gid and group haven't already been allocated */
106 gr.gr_gid = gid;
107 gr.gr_name = group;
108 if (group_study(filename, &gr))
109 return 1;
110
111 /* add entry to group */
112 etc_group = fopen(filename, "a");
113 if (!etc_group) {
114 perror_msg_and_die("%s", filename);
115 }
116 fprintf(etc_group, entryfmt, group, default_passwd, gr.gr_gid, "");
117 fclose(etc_group);
118
119 /* add entry to gshadow if necessary */
120 if (access(gshadow, F_OK|W_OK) == 0) {
121 etc_gshadow = xfopen(gshadow, "a");
122 fprintf(etc_gshadow, "%s:!::\n", group);
123 fclose(etc_gshadow);
124 }
125
126 /* return 1; */
127 return 0;
128}
129
130/*
131 * addgroup will take a login_name as its first parameter.
132 *
133 * gid
134 *
135 * can be customized via command-line parameters.
136 * ________________________________________________________________________ */
137int addgroup_main(int argc, char **argv)
138{
139 int i;
140 char opt;
141 char *group;
142 gid_t gid = 0;
143
144 /* get remaining args */
145 for (i = 1; i < argc; i++) {
146 if (argv[i][0] == '-') {
147 opt = argv[i][1];
148 switch (opt) {
149 case 'h':
150 show_usage();
151 break;
152 case 'g':
153 gid = strtol(argv[++i], NULL, 10);
154 break;
155 default:
156 error_msg_and_die("addgroup: invalid option -- %c\n", opt);
157 }
158 } else {
159 break;
160 }
161 }
162
163 if (i >= argc) {
164 show_usage();
165 } else {
166 group = argv[i];
167 }
168
169 if (geteuid() != 0) {
170 error_msg_and_die
171 ("addgroup: Only root may add a group to the system.\n");
172 }
173
174 /* werk */
175 return addgroup(GROUP_FILE, group, gid);
176}
177
178/* $Id: addgroup.c,v 1.1 2001/08/21 16:18:59 andersen Exp $ */