~ubuntu-branches/ubuntu/utopic/libuser/utopic-proposed

« back to all changes in this revision

Viewing changes to apps/lnewusers.c

  • Committer: Bazaar Package Importer
  • Author(s): Ghe Rivero
  • Date: 2005-09-30 16:22:04 UTC
  • Revision ID: james.westby@ubuntu.com-20050930162204-qubxaa7e2lbovdgh
Tags: upstream-0.54.dfsg.1
ImportĀ upstreamĀ versionĀ 0.54.dfsg.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2001, 2002, 2004 Red Hat, Inc.
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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.
 
17
 */
 
18
 
 
19
#ident "$Id: lnewusers.c,v 1.21 2005/09/12 21:52:02 mitr Exp $"
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include "config.h"
 
23
#endif
 
24
#include <errno.h>
 
25
#include <inttypes.h>
 
26
#include <libintl.h>
 
27
#include <limits.h>
 
28
#include <locale.h>
 
29
#include <popt.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include "../lib/user.h"
 
33
#include "apputil.h"
 
34
 
 
35
int
 
36
main(int argc, const char **argv)
 
37
{
 
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,
 
42
            nocreatemail = FALSE;
 
43
        int c;
 
44
        char *file = NULL, **fields;
 
45
        FILE *fp = stdin;
 
46
        uid_t uid;
 
47
        gid_t gid;
 
48
        char *homedir, *gidstring;
 
49
        const char *skeleton;
 
50
        char *p;
 
51
        GValueArray *values = NULL;
 
52
        GValue *value, val;
 
53
        char buf[LINE_MAX];
 
54
        poptContext popt;
 
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},
 
64
                POPT_AUTOHELP
 
65
                POPT_TABLEEND
 
66
        };
 
67
 
 
68
        /* Initialize i18n support. */
 
69
        bindtextdomain(PACKAGE, LOCALEDIR);
 
70
        textdomain(PACKAGE);
 
71
        setlocale(LC_ALL, "");
 
72
 
 
73
        /* Parse arguments. */
 
74
        popt = poptGetContext("lnewusers", argc, argv, options, 0);
 
75
        poptSetOtherOptionHelp(popt, _("[OPTION...]"));
 
76
        c = poptGetNextOpt(popt);
 
77
        if (c != -1) {
 
78
                fprintf(stderr, _("Error parsing arguments: %s.\n"),
 
79
                        poptStrerror(c));
 
80
                poptPrintUsage(popt, stderr, 0);
 
81
                exit(1);
 
82
        }
 
83
 
 
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);
 
88
        if (ctx == NULL) {
 
89
                fprintf(stderr, _("Error initializing %s: %s.\n"), PACKAGE,
 
90
                        lu_strerror(error));
 
91
                return 1;
 
92
        }
 
93
 
 
94
        /* Open the file we're going to look at. */
 
95
        if (file != NULL) {
 
96
                fp = fopen(file, "r");
 
97
                if (fp == NULL) {
 
98
                        fprintf(stderr, _("Error opening `%s': %s.\n"),
 
99
                                file, strerror(errno));
 
100
                        return 2;
 
101
                }
 
102
        } else {
 
103
                fp = stdin;
 
104
        }
 
105
 
 
106
        ent = lu_ent_new();
 
107
        groupEnt = lu_ent_new();
 
108
 
 
109
        while (fgets(buf, sizeof(buf), fp)) {
 
110
                intmax_t imax;
 
111
 
 
112
                /* Strip off the end-of-line terminators. */
 
113
                if (strchr(buf, '\r')) {
 
114
                        p = strchr(buf, '\r');
 
115
                        *p = '\0';
 
116
                }
 
117
                if (strchr(buf, '\n')) {
 
118
                        p = strchr(buf, '\n');
 
119
                        *p = '\0';
 
120
                }
 
121
 
 
122
                /* Make sure the line splits into *exactly* seven fields. */
 
123
                fields = g_strsplit(buf, ":", 7);
 
124
                if (g_strv_length(fields) != 7) {
 
125
                        fprintf(stderr,
 
126
                                _("Error creating account for `%s': line "
 
127
                                  "improperly formatted.\n"), buf);
 
128
                        g_strfreev(fields);
 
129
                        continue;
 
130
                }
 
131
 
 
132
                errno = 0;
 
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]);
 
137
                        g_strfreev(fields);
 
138
                        continue;
 
139
                }
 
140
                /* Sorry, but we're bastards here.  No root accounts. */
 
141
                uid = imax;
 
142
                if (uid == 0) {
 
143
                        g_print(_("Refusing to create account with UID 0.\n"));
 
144
                        g_strfreev(fields);
 
145
                        continue;
 
146
                }
 
147
 
 
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];
 
154
                } else {
 
155
                        gidstring = fields[0];
 
156
                }
 
157
 
 
158
                /* Try to convert the field to a number. */
 
159
                p = NULL;
 
160
                errno = 0;
 
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,
 
172
                                                                      0);
 
173
                                        gid = lu_value_get_id(value);
 
174
                                        g_assert(gid != LU_VALUE_INVALID_ID);
 
175
                                }
 
176
                                creategroup = FALSE;
 
177
                        } else {
 
178
                                /* Mark that we need to create a group for the
 
179
                                 * user to be in. */
 
180
                                creategroup = TRUE;
 
181
                        }
 
182
                } else {
 
183
                        /* It's a group number -- see if it's being used. */
 
184
                        gid = imax;
 
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,
 
190
                                                                      0);
 
191
                                        gid = lu_value_get_id(value);
 
192
                                        g_assert(gid != LU_VALUE_INVALID_ID);
 
193
                                }
 
194
                                creategroup = FALSE;
 
195
                        } else {
 
196
                                /* Mark that we need to create a group for the
 
197
                                 * user to be in. */
 
198
                                creategroup = TRUE;
 
199
                        }
 
200
                }
 
201
                /* If we need to create a group, create a template group and
 
202
                 * try to apply what the user has asked us to. */
 
203
                if (creategroup) {
 
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);
 
212
                                g_value_unset(&val);
 
213
                        } else {
 
214
                                lu_group_default(ctx, gidstring, FALSE, ent);
 
215
                        }
 
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);
 
223
                        } else {
 
224
                                /* Aargh!  Abandon all hope. */
 
225
                                fprintf(stderr,
 
226
                                        _("Error creating group for `%s' with "
 
227
                                          "GID %jd: %s\n"), fields[0], imax,
 
228
                                        lu_strerror(error));
 
229
                                g_strfreev(fields);
 
230
                                continue;
 
231
                        }
 
232
                }
 
233
 
 
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);
 
240
                g_value_unset(&val);
 
241
                lu_value_init_set_id(&val, gid);
 
242
                lu_ent_clear(ent, LU_GIDNUMBER);
 
243
                lu_ent_add(ent, LU_GIDNUMBER, &val);
 
244
                g_value_unset(&val);
 
245
 
 
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);
 
253
                }
 
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);
 
259
                } else {
 
260
                        values = lu_ent_get(ent, LU_HOMEDIRECTORY);
 
261
                        if (values != NULL) {
 
262
                                value = g_value_array_get_nth(values,
 
263
                                                              0);
 
264
                                homedir = g_strdup(g_value_get_string(value));
 
265
                        } else {
 
266
                                homedir = g_strdup_printf("/home/%s",
 
267
                                                          fields[0]);
 
268
                        }
 
269
                }
 
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);
 
274
                }
 
275
 
 
276
                g_value_unset(&val);
 
277
 
 
278
                /* Now try to add the user's account. */
 
279
                if (lu_user_add(ctx, ent, &error)) {
 
280
                        lu_hup_nscd();
 
281
                        if (!lu_user_setpass(ctx, ent, fields[1], FALSE,
 
282
                                             &error)) {
 
283
                                fprintf(stderr,
 
284
                                        _("Error setting initial password for "
 
285
                                          "%s: %s\n"), fields[0],
 
286
                                        lu_strerror(error));
 
287
                                if (error) {
 
288
                                        lu_error_free(&error);
 
289
                                }
 
290
                        }
 
291
                        /* Unless the nocreatehomedirs flag was given, attempt
 
292
                         * to create the user's home directory. */
 
293
                        if (!nocreatehome) {
 
294
                                skeleton = lu_cfg_read_single(ctx,
 
295
                                                              "defaults/skeleton",
 
296
                                                              "/etc/skel");
 
297
                                if (lu_homedir_populate(skeleton,
 
298
                                                        homedir,
 
299
                                                        uid,
 
300
                                                        gid,
 
301
                                                        0700,
 
302
                                                        &error) == FALSE) {
 
303
                                        fprintf(stderr,
 
304
                                                _("Error creating home "
 
305
                                                  "directory for %s: %s\n"),
 
306
                                                fields[0], lu_strerror(error));
 
307
                                        if (error) {
 
308
                                                lu_error_free(&error);
 
309
                                        }
 
310
                                }
 
311
                        }
 
312
                        /* Unless the nocreatemail flag was given, give the
 
313
                         * user a mail spool. */
 
314
                        if (!nocreatemail) {
 
315
                                if (!lu_mailspool_create_remove(ctx, ent,
 
316
                                                                TRUE))
 
317
                                        fprintf(stderr,
 
318
                                                _("Error creating mail spool "
 
319
                                                  "for %s.\n"), fields[0]);
 
320
 
 
321
                        }
 
322
                } else {
 
323
                        fprintf(stderr,
 
324
                                _("Error creating user account for %s: %s\n"),
 
325
                                fields[0], lu_strerror(error));
 
326
                        if (error) {
 
327
                                lu_error_free(&error);
 
328
                        }
 
329
                }
 
330
 
 
331
                g_free(homedir);
 
332
                g_strfreev(fields);
 
333
                lu_ent_clear_all(ent);
 
334
                lu_ent_clear_all(groupEnt);
 
335
        }
 
336
 
 
337
        lu_ent_free(ent);
 
338
 
 
339
        lu_end(ctx);
 
340
 
 
341
        return 0;
 
342
}