2
* Copyright (C) 2001, 2002, 2004 Red Hat, Inc.
4
* This is free software; you can redistribute it and/or modify it under
5
* the terms of the GNU Library General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU Library General Public
15
* License along with this program; if not, write to the Free Software
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
#ident "$Id: lnewusers.c,v 1.21 2005/09/12 21:52:02 mitr Exp $"
32
#include "../lib/user.h"
36
main(int argc, const char **argv)
38
struct lu_context *ctx = NULL;
39
struct lu_error *error = NULL;
40
struct lu_ent *ent = NULL, *groupEnt = NULL;
41
int interactive = FALSE, nocreatehome = FALSE, creategroup = FALSE,
44
char *file = NULL, **fields;
48
char *homedir, *gidstring;
51
GValueArray *values = NULL;
55
struct poptOption options[] = {
56
{"interactive", 'i', POPT_ARG_NONE, &interactive, 0,
57
"prompt for all information", NULL},
58
{"file", 'f', POPT_ARG_STRING, &file, 0,
59
"file with user information records", "STDIN"},
60
{"nocreatehome", 'M', POPT_ARG_NONE, &nocreatehome, 0,
61
"don't create home directories", NULL},
62
{"nocreatemail", 'n', POPT_ARG_NONE, &nocreatemail, 0,
63
"don't create mail spools", NULL},
68
/* Initialize i18n support. */
69
bindtextdomain(PACKAGE, LOCALEDIR);
71
setlocale(LC_ALL, "");
73
/* Parse arguments. */
74
popt = poptGetContext("lnewusers", argc, argv, options, 0);
75
poptSetOtherOptionHelp(popt, _("[OPTION...]"));
76
c = poptGetNextOpt(popt);
78
fprintf(stderr, _("Error parsing arguments: %s.\n"),
80
poptPrintUsage(popt, stderr, 0);
84
/* Start up the library. */
85
ctx = lu_start(NULL, lu_user, NULL, NULL,
86
interactive ? lu_prompt_console :
87
lu_prompt_console_quiet, NULL, &error);
89
fprintf(stderr, _("Error initializing %s: %s.\n"), PACKAGE,
94
/* Open the file we're going to look at. */
96
fp = fopen(file, "r");
98
fprintf(stderr, _("Error opening `%s': %s.\n"),
99
file, strerror(errno));
107
groupEnt = lu_ent_new();
109
while (fgets(buf, sizeof(buf), fp)) {
112
/* Strip off the end-of-line terminators. */
113
if (strchr(buf, '\r')) {
114
p = strchr(buf, '\r');
117
if (strchr(buf, '\n')) {
118
p = strchr(buf, '\n');
122
/* Make sure the line splits into *exactly* seven fields. */
123
fields = g_strsplit(buf, ":", 7);
124
if (g_strv_length(fields) != 7) {
126
_("Error creating account for `%s': line "
127
"improperly formatted.\n"), buf);
133
imax = strtoimax(fields[2], &p, 10);
134
if (errno != 0 || *p != 0 || p == fields[2]
135
|| (uid_t)imax != imax) {
136
g_print(_("Invalid user ID %s\n"), fields[2]);
140
/* Sorry, but we're bastards here. No root accounts. */
143
g_print(_("Refusing to create account with UID 0.\n"));
148
/* Try to figure out if the field is the name of a group, or
149
* a gid. If it's just empty, make it the same as the user's
150
* name. FIXME: provide some way to set a default other than
151
* the user's own name, like "users" or something. */
152
if (strlen(fields[3]) > 0) {
153
gidstring = fields[3];
155
gidstring = fields[0];
158
/* Try to convert the field to a number. */
161
imax = strtoimax(gidstring, &p, 10);
162
gid = LU_VALUE_INVALID_ID;
163
if (errno != 0 || *p != '\0' || p == gidstring
164
|| (gid_t)imax != imax) {
165
/* It's not a number, so it's a group name --
166
* see if it's being used. */
167
if (lu_group_lookup_name(ctx, gidstring, ent, &error)) {
168
/* Retrieve the group's GID. */
169
values = lu_ent_get(ent, LU_GIDNUMBER);
170
if (values != NULL) {
171
value = g_value_array_get_nth(values,
173
gid = lu_value_get_id(value);
174
g_assert(gid != LU_VALUE_INVALID_ID);
178
/* Mark that we need to create a group for the
183
/* It's a group number -- see if it's being used. */
185
if (lu_group_lookup_id(ctx, gid, ent, &error)) {
186
/* Retrieve the group's GID. */
187
values = lu_ent_get(ent, LU_GIDNUMBER);
188
if (values != NULL) {
189
value = g_value_array_get_nth(values,
191
gid = lu_value_get_id(value);
192
g_assert(gid != LU_VALUE_INVALID_ID);
196
/* Mark that we need to create a group for the
201
/* If we need to create a group, create a template group and
202
* try to apply what the user has asked us to. */
204
/* If we got a GID, then we need to use the user's name,
205
* otherwise we need to use the default group name. */
206
if (gid != LU_VALUE_INVALID_ID) {
207
lu_group_default(ctx, fields[0], FALSE, ent);
208
memset(&val, 0, sizeof(val));
209
lu_value_init_set_id(&val, gid);
210
lu_ent_clear(ent, LU_GIDNUMBER);
211
lu_ent_add(ent, LU_GIDNUMBER, &val);
214
lu_group_default(ctx, gidstring, FALSE, ent);
216
/* Try to create the group, and if it works, get its
217
* GID, which we need to give to this user. */
218
if (lu_group_add(ctx, ent, &error)) {
219
values = lu_ent_get(ent, LU_GIDNUMBER);
220
value = g_value_array_get_nth(values, 0);
221
gid = lu_value_get_id(value);
222
g_assert(gid != LU_VALUE_INVALID_ID);
224
/* Aargh! Abandon all hope. */
226
_("Error creating group for `%s' with "
227
"GID %jd: %s\n"), fields[0], imax,
234
/* Create a new user record, and set the user's primary GID. */
235
lu_user_default(ctx, fields[0], FALSE, ent);
236
memset(&val, 0, sizeof(val));
237
lu_value_init_set_id(&val, uid);
238
lu_ent_clear(ent, LU_UIDNUMBER);
239
lu_ent_add(ent, LU_UIDNUMBER, &val);
241
lu_value_init_set_id(&val, gid);
242
lu_ent_clear(ent, LU_GIDNUMBER);
243
lu_ent_add(ent, LU_GIDNUMBER, &val);
246
/* Set other fields if we've got them. */
247
memset(&val, 0, sizeof(val));
248
g_value_init(&val, G_TYPE_STRING);
249
if (strlen(fields[4]) > 0) {
250
g_value_set_string(&val, fields[4]);
251
lu_ent_clear(ent, LU_GECOS);
252
lu_ent_add(ent, LU_GECOS, &val);
254
if (strlen(fields[5]) > 0) {
255
homedir = g_strdup(fields[5]);
256
g_value_set_string(&val, homedir);
257
lu_ent_clear(ent, LU_HOMEDIRECTORY);
258
lu_ent_add(ent, LU_HOMEDIRECTORY, &val);
260
values = lu_ent_get(ent, LU_HOMEDIRECTORY);
261
if (values != NULL) {
262
value = g_value_array_get_nth(values,
264
homedir = g_strdup(g_value_get_string(value));
266
homedir = g_strdup_printf("/home/%s",
270
if (strlen(fields[6]) > 0) {
271
g_value_set_string(&val, fields[6]);
272
lu_ent_clear(ent, LU_LOGINSHELL);
273
lu_ent_add(ent, LU_LOGINSHELL, &val);
278
/* Now try to add the user's account. */
279
if (lu_user_add(ctx, ent, &error)) {
281
if (!lu_user_setpass(ctx, ent, fields[1], FALSE,
284
_("Error setting initial password for "
285
"%s: %s\n"), fields[0],
288
lu_error_free(&error);
291
/* Unless the nocreatehomedirs flag was given, attempt
292
* to create the user's home directory. */
294
skeleton = lu_cfg_read_single(ctx,
297
if (lu_homedir_populate(skeleton,
304
_("Error creating home "
305
"directory for %s: %s\n"),
306
fields[0], lu_strerror(error));
308
lu_error_free(&error);
312
/* Unless the nocreatemail flag was given, give the
313
* user a mail spool. */
315
if (!lu_mailspool_create_remove(ctx, ent,
318
_("Error creating mail spool "
319
"for %s.\n"), fields[0]);
324
_("Error creating user account for %s: %s\n"),
325
fields[0], lu_strerror(error));
327
lu_error_free(&error);
333
lu_ent_clear_all(ent);
334
lu_ent_clear_all(groupEnt);