]> granicus.if.org Git - shadow/blob - src/useradd.c
[svn-upgrade] Integrating new upstream version, shadow (20000826)
[shadow] / src / useradd.c
1 /*
2  * Copyright 1991 - 1994, Julianne Frances Haugh
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <config.h>
31
32 #include "rcsid.h"
33 RCSID(PKG_VER "$Id: useradd.c,v 1.17 2000/08/26 18:27:18 marekm Exp $")
34
35 #include "prototypes.h"
36 #include "defines.h"
37 #include "chkname.h"
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <stdio.h>
41 #include <errno.h>
42 #include <pwd.h>
43 #include <grp.h>
44 #include <ctype.h>
45 #include <fcntl.h>
46 #include <time.h>
47
48 #include "pwauth.h"
49 #if HAVE_LASTLOG_H
50 #include <lastlog.h>
51 #else
52 #include "lastlog_.h"
53 #endif
54 #include "faillog.h"
55
56 #ifndef SKEL_DIR
57 #define SKEL_DIR "/etc/skel"
58 #endif
59
60 #ifndef USER_DEFAULTS_FILE
61 #define USER_DEFAULTS_FILE "/etc/default/useradd"
62 #define NEW_USER_FILE "/etc/default/nuaddXXXXXX"
63 #endif
64
65 /*
66  * Needed for MkLinux DR1/2/2.1 - J.
67  */
68 #ifndef LASTLOG_FILE
69 #define LASTLOG_FILE "/var/log/lastlog"
70 #endif
71
72 /*
73  * These defaults are used if there is no defaults file.
74  */
75 static gid_t def_group = 100;
76 static const char *def_gname = "other";
77 static const char *def_home = "/home";
78 static const char *def_shell = "";
79 static const char *def_template = SKEL_DIR;
80 #ifdef SHADOWPWD
81 static long def_inactive = -1;
82 static const char *def_expire = "";
83 #endif
84
85 static char     def_file[] = USER_DEFAULTS_FILE;
86
87 #define VALID(s)        (strcspn (s, ":\n") == strlen (s))
88
89 static const char *user_name = "";
90 static const char *user_pass = "!";
91 static uid_t user_id;
92 static gid_t user_gid;
93 static const char *user_comment = "";
94 static const char *user_home = "";
95 static const char *user_shell = "";
96 #ifdef  SHADOWPWD
97 static long user_expire = -1;
98 static int is_shadow_pwd;
99 #endif
100 #ifdef SHADOWGRP
101 static int is_shadow_grp;
102 #endif
103 static char *user_groups[NGROUPS_MAX+1];  /* NULL-terminated list */
104 static int do_grp_update = 0;  /* group files need to be updated */
105
106 static char     *Prog;
107
108 static int
109         uflg = 0, /* specify user ID for new account */
110         oflg = 0, /* permit non-unique user ID to be specified with -u */
111         gflg = 0, /* primary group ID for new account */
112         Gflg = 0, /* secondary group set for new account */
113         dflg = 0, /* home directory for new account */
114         bflg = 0, /* new default root of home directory */
115         sflg = 0, /* shell program for new account */
116         cflg = 0, /* comment (GECOS) field for new account */
117         mflg = 0, /* create user's home directory if it doesn't exist */
118         kflg = 0, /* specify a directory to fill new user directory */
119         fflg = 0, /* days until account with expired password is locked */
120         eflg = 0, /* days since 1970-01-01 when account is locked */
121         Dflg = 0; /* set/show new user default values */
122
123 #ifdef AUTH_METHODS
124 static int Aflg = 0; /* specify authentication method for user */
125 static char user_auth[1024];
126 static char *auth_arg;
127 #endif
128
129 extern char *optarg;
130 extern int optind;
131
132 #ifdef NDBM
133 extern  int     pw_dbm_mode;
134 #ifdef  SHADOWPWD
135 extern  int     sp_dbm_mode;
136 #endif
137 extern  int     gr_dbm_mode;
138 #ifdef  SHADOWGRP
139 extern  int     sg_dbm_mode;
140 #endif
141 #endif
142
143 static int      home_added;
144
145 #ifdef NDBM
146 static int      pw_dbm_added;
147 static int      gr_dbm_added;
148 #ifdef  SHADOWPWD
149 static int      sp_dbm_added;
150 #endif
151 #ifdef  SHADOWGRP
152 static int      sg_dbm_added;
153 #endif
154 #endif  /* NDBM */
155
156 #include "groupio.h"
157
158 #ifdef  SHADOWGRP
159 #include "sgroupio.h"
160 #endif
161
162 #include "pwio.h"
163
164 #ifdef  SHADOWPWD
165 #include "shadowio.h"
166 #endif
167
168 #include "getdef.h"
169
170 /*
171  * exit status values
172  */
173 #define E_SUCCESS       0       /* success */
174 #define E_PW_UPDATE     1       /* can't update password file */
175 #define E_USAGE         2       /* bad command syntax */
176 #define E_BAD_ARG       3       /* invalid argument to option */
177 #define E_UID_IN_USE    4       /* uid already in use (and no -o) */
178 #define E_NOTFOUND      6       /* specified group doesn't exist */
179 #define E_NAME_IN_USE   9       /* username already in use */
180 #define E_GRP_UPDATE    10      /* can't update group file */
181 #define E_HOMEDIR       12      /* can't create home directory */
182
183 #ifdef SVR4
184 #define DGROUP  "defgroup="
185 #define HOME    "defparent="
186 #define SHELL   "defshell="
187 #define INACT   "definact="
188 #define EXPIRE  "defexpire="
189 #define SKEL    "defskel="
190 #else
191 #define DGROUP  "GROUP="
192 #define HOME    "HOME="
193 #define SHELL   "SHELL="
194 #define INACT   "INACTIVE="
195 #define EXPIRE  "EXPIRE="
196 #define SKEL    "SKEL="
197 #endif
198
199 /* local function prototypes */
200 static void fail_exit(int);
201 static struct group *getgr_nam_gid(const char *);
202 static long get_number(const char *);
203 static void get_defaults(void);
204 static void show_defaults(void);
205 static int set_defaults(void);
206 static int get_groups(char *);
207 static void usage(void);
208 static void new_pwent(struct passwd *);
209 #ifdef SHADOWPWD
210 static long scale_age(long);
211 static void new_spent(struct spwd *);
212 #endif
213 static void grp_update(void);
214 static void find_new_uid(void);
215 #ifdef AUTH_METHODS
216 static void convert_auth(char *, const char *);
217 static int valid_auth(const char *);
218 #endif
219 static void process_flags(int argc, char **argv);
220 static void close_files(void);
221 static void open_files(void);
222 static void faillog_reset(uid_t);
223 static void lastlog_reset(uid_t);
224 static void usr_update(void);
225 static void create_home(void);
226
227 /*
228  * fail_exit - undo as much as possible
229  */
230
231 static void
232 fail_exit(int code)
233 {
234 #ifdef NDBM
235         struct  passwd  pwent;
236
237         if (pw_dbm_added) {
238                 pwent.pw_name = user_name;
239                 pwent.pw_uid = user_id;
240                 pw_dbm_remove(&pwent);
241         }
242         if (gr_dbm_added)
243                 fprintf(stderr, _("%s: rebuild the group database\n"), Prog);
244 #ifdef  SHADOWPWD
245         if (sp_dbm_added)
246                 sp_dbm_remove(user_name);
247 #endif
248 #ifdef  SHADOWGRP
249         if (sg_dbm_added)
250                 fprintf(stderr, _("%s: rebuild the shadow group database\n"),
251                         Prog);
252 #endif
253 #endif  /* NDBM */
254         if (home_added)
255                 rmdir(user_home);
256
257         SYSLOG((LOG_INFO, "failed adding user `%s', data deleted\n",
258                 user_name));
259         exit(code);
260 }
261
262
263 static struct group *
264 getgr_nam_gid(const char *name)
265 {
266         gid_t gid;
267         char *ep;
268
269         gid = strtol(name, &ep, 10);
270         if (*name != '\0' && *ep == '\0')  /* valid numeric gid */
271                 return getgrgid(gid);
272
273         return getgrnam(name);
274 }
275
276
277 static long
278 get_number(const char *cp)
279 {
280         long val;
281         char *ep;
282
283         val = strtol(cp, &ep, 10);
284         if (*cp != '\0' && *ep == '\0')  /* valid number */
285                 return val;
286
287         fprintf(stderr, _("%s: invalid numeric argument `%s'\n"), Prog, cp);
288         exit(E_BAD_ARG);
289 }
290
291 #define MATCH(x,y) (strncmp((x),(y),strlen(y)) == 0)
292
293 /*
294  * get_defaults - read the defaults file
295  *
296  *      get_defaults() reads the defaults file for this command.  It sets
297  *      the various values from the file, or uses built-in default values
298  *      if the file does not exist.
299  */
300
301 static void
302 get_defaults(void)
303 {
304         FILE *fp;
305         char buf[1024];
306         char *cp, *ep;
307         const struct group *grp;
308         long val;
309
310         /*
311          * Open the defaults file for reading.
312          */
313
314         if (!(fp = fopen(def_file, "r")))
315                 return;
316
317         /*
318          * Read the file a line at a time.  Only the lines that have
319          * relevant values are used, everything else can be ignored.
320          */
321
322         while (fgets(buf, sizeof buf, fp)) {
323                 if ((cp = strrchr (buf, '\n')))
324                         *cp = '\0';
325
326                 if (!(cp = strchr(buf, '=')))
327                         continue;
328
329                 cp++;
330
331                 /*
332                  * Primary GROUP identifier
333                  */
334
335                 if (MATCH(buf, DGROUP)) {
336                         val = strtol(cp, &ep, 10);
337                         if (*cp != '\0' && *ep == '\0') {  /* valid number */
338                                 def_group = val;
339                                 if ((grp = getgrgid(def_group))) {
340                                         def_gname = xstrdup(grp->gr_name);
341                                 } else {
342                                         fprintf(stderr,
343                                                 _("%s: unknown gid %s\n"),
344                                                 Prog, cp);
345                                 }
346                         } else if ((grp = getgrnam(cp))) {
347                                 def_group = grp->gr_gid;
348                                 def_gname = xstrdup(cp);
349                         } else {
350                                 fprintf(stderr, _("%s: unknown group %s\n"),
351                                         Prog, cp);
352                         }
353                 }
354                 
355                 /*
356                  * Default HOME filesystem
357                  */
358                  
359                 else if (MATCH(buf, HOME)) {
360                         def_home = xstrdup(cp);
361                 }
362
363                 /*
364                  * Default Login Shell command
365                  */
366
367                 else if (MATCH(buf, SHELL)) {
368                         def_shell = xstrdup(cp);
369                 }
370
371 #ifdef SHADOWPWD
372                 /*
373                  * Default Password Inactive value
374                  */
375
376                 else if (MATCH(buf, INACT)) {
377                         val = strtol(cp, &ep, 10);
378                         if (*cp != '\0' && *ep == '\0')  /* valid number */
379                                 def_inactive = val;
380                         else
381                                 def_inactive = -1;
382                 }
383                 
384                 /*
385                  * Default account expiration date
386                  */
387
388                 else if (MATCH(buf, EXPIRE)) {
389                         def_expire = xstrdup(cp);
390                 }
391 #endif
392
393                 /*
394                  * Default Skeleton information
395                  */
396
397                 else if (MATCH(buf, SKEL)) {
398                         if (*cp == '\0')
399                                 cp = SKEL_DIR;  /* XXX warning: const */
400                         
401                         def_template = xstrdup(cp);
402                 }
403         }
404 }
405
406
407 /*
408  * show_defaults - show the contents of the defaults file
409  *
410  *      show_defaults() displays the values that are used from the default
411  *      file and the built-in values.
412  */
413
414 static void
415 show_defaults(void)
416 {
417 #ifdef SVR4
418         printf(_("group=%s,%ld  basedir=%s  skel=%s\n"),
419                 def_gname, (long) def_group, def_home, def_template);
420
421         printf(_("shell=%s  "), def_shell);
422 #ifdef SHADOWPWD
423         printf(_("inactive=%ld  expire=%s"), def_inactive, def_expire);
424 #endif
425         printf("\n");
426 #else /* !SVR4 */
427         printf(_("GROUP=%ld\n"), (long) def_group);
428         printf(_("HOME=%s\n"), def_home);
429 #ifdef SHADOWPWD
430         printf(_("INACTIVE=%ld\n"), def_inactive);
431         printf(_("EXPIRE=%s\n"), def_expire);
432 #endif
433         printf(_("SHELL=%s\n"), def_shell);
434         printf(_("SKEL=%s\n"), def_template);
435 #endif /* !SVR4 */
436 }
437
438 /*
439  * set_defaults - write new defaults file
440  *
441  *      set_defaults() re-writes the defaults file using the values that
442  *      are currently set.  Duplicated lines are pruned, missing lines are
443  *      added, and unrecognized lines are copied as is.
444  */
445
446 static int
447 set_defaults(void)
448 {
449         FILE    *ifp;
450         FILE    *ofp;
451         char    buf[1024];
452         static  char    new_file[] = NEW_USER_FILE;
453         char    *cp;
454         int     out_group = 0;
455         int     out_home = 0;
456         int     out_inactive = 0;
457         int     out_expire = 0;
458         int     out_shell = 0;
459         int     out_skel = 0;
460 #ifdef  SVR4
461         int     out_gname = 0;
462 #endif
463
464         /*
465          * Create a temporary file to copy the new output to.
466          */
467
468         mktemp (new_file);
469         if (!(ofp = fopen (new_file, "w"))) {
470                 fprintf(stderr, _("%s: cannot create new defaults file\n"),
471                         Prog);
472                 return -1;
473         }
474
475         /*
476          * Open the existing defaults file and copy the lines to the
477          * temporary file, using any new values.  Each line is checked
478          * to insure that it is not output more than once.
479          */
480
481         if (!(ifp = fopen(def_file, "r"))) {
482                 fprintf(ofp, "# useradd defaults file\n");
483                 goto skip;
484         }
485
486         while (fgets(buf, sizeof buf, ifp)) {
487                 if ((cp = strrchr(buf, '\n')))
488                         *cp = '\0';
489
490                 if (!out_group && MATCH(buf, DGROUP)) {
491                         fprintf(ofp, DGROUP "%d\n", (int) def_group);
492                         out_group++;
493                 }
494 #ifdef  SVR4
495                 else if (!out_gname && MATCH(buf, "defgname=")) {
496                         fprintf(ofp, "defgname=%s\n", def_gname);
497                         out_gname++;
498                 }
499 #endif
500                 else if (!out_home && MATCH(buf, HOME)) {
501                         fprintf(ofp, HOME "%s\n", def_home);
502                         out_home++;
503 #ifdef  SHADOWPWD
504                 } else if (!out_inactive && MATCH(buf, INACT)) {
505                         fprintf(ofp, INACT "%ld\n", def_inactive);
506                         out_inactive++;
507                 } else if (!out_expire && MATCH(buf, EXPIRE)) {
508                         fprintf(ofp, EXPIRE "%s\n", def_expire);
509                         out_expire++;
510                 }
511 #endif
512                 else if (!out_shell && MATCH(buf, SHELL)) {
513                         fprintf(ofp, SHELL "%s\n", def_shell);
514                         out_shell++;
515                 }
516                 else if (!out_skel && MATCH(buf, SKEL)) {
517                         fprintf(ofp, SKEL "%s\n", def_template);
518                         out_skel++;
519                 }
520                 else
521                         fprintf(ofp, "%s\n", buf);
522         }
523         fclose(ifp);
524
525 skip:
526         /*
527          * Check each line to insure that every line was output.  This
528          * causes new values to be added to a file which did not previously
529          * have an entry for that value.
530          */
531
532         if (!out_group)
533                 fprintf(ofp, DGROUP "%d\n", (int) def_group);
534         if (!out_home)
535                 fprintf(ofp, HOME "%s\n", def_home);
536 #ifdef  SHADOWPWD
537         if (!out_inactive)
538                 fprintf(ofp, INACT "%ld\n", def_inactive);
539         if (!out_expire)
540                 fprintf(ofp, EXPIRE "%s\n", def_expire);
541 #endif
542         if (!out_shell)
543                 fprintf(ofp, SHELL "%s\n", def_shell);
544         if (!out_skel)
545                 fprintf(ofp, SKEL "%s\n", def_template);
546
547         /*
548          * Flush and close the file.  Check for errors to make certain
549          * the new file is intact.
550          */
551
552         fflush(ofp);
553         if (ferror(ofp) || fclose(ofp)) {
554                 unlink(new_file);
555                 return -1;
556         }
557
558         /*
559          * Rename the current default file to its backup name.
560          */
561
562         snprintf(buf, sizeof buf, "%s-", def_file);
563         if (rename(def_file, buf) && errno != ENOENT) {
564                 snprintf(buf, sizeof buf, _("%s: rename: %s"), Prog, def_file);
565                 perror(buf);
566                 unlink(new_file);
567                 return -1;
568         }
569
570         /*
571          * Rename the new default file to its correct name.
572          */
573
574         if (rename(new_file, def_file)) {
575                 snprintf(buf, sizeof buf, _("%s: rename: %s"), Prog, new_file);
576                 perror(buf);
577                 return -1;
578         }
579 #ifdef SHADOWPWD
580         SYSLOG((LOG_INFO,
581                 "defaults: group=%d, home=%s, inactive=%ld, expire=%s\n",
582                 (int) def_group, def_home, def_inactive, def_expire));
583 #else
584         SYSLOG((LOG_INFO, "defaults: group=%d, home=%s\n",
585                 (int) def_group, def_home));
586 #endif
587         return 0;
588 }
589
590 /*
591  * get_groups - convert a list of group names to an array of group IDs
592  *
593  *      get_groups() takes a comma-separated list of group names and
594  *      converts it to a NULL-terminated array.  Any unknown group
595  *      names are reported as errors.
596  */
597
598 static int
599 get_groups(char *list)
600 {
601         char *cp;
602         const struct group *grp;
603         int errors = 0;
604         int ngroups = 0;
605
606         /*
607          * Initialize the list to be empty
608          */
609
610         user_groups[0] = (char *) 0;
611
612         if (! *list)
613                 return 0;
614
615         /*
616          * So long as there is some data to be converted, strip off
617          * each name and look it up.  A mix of numerical and string
618          * values for group identifiers is permitted.
619          */
620
621         do {
622                 /*
623                  * Strip off a single name from the list
624                  */
625
626                 if ((cp = strchr (list, ',')))
627                         *cp++ = '\0';
628
629                 /*
630                  * Names starting with digits are treated as numerical
631                  * GID values, otherwise the string is looked up as is.
632                  */
633
634                 grp = getgr_nam_gid(list);
635
636                 /*
637                  * There must be a match, either by GID value or by
638                  * string name.
639                  */
640
641                 if (! grp) {
642                         fprintf(stderr, _("%s: unknown group %s\n"),
643                                 Prog, list);
644                         errors++;
645                 }
646                 list = cp;
647
648                 /*
649                  * If the group doesn't exist, don't dump core...
650                  * Instead, try the next one.  --marekm
651                  */
652                 if (! grp)
653                         continue;
654
655 #ifdef  USE_NIS
656                 /*
657                  * Don't add this group if they are an NIS group.  Tell
658                  * the user to go to the server for this group.
659                  */
660
661                 if (__isgrNIS ()) {
662                         fprintf(stderr, _("%s: group `%s' is a NIS group.\n"),
663                                 Prog, grp->gr_name);
664                         continue;
665                 }
666 #endif
667
668                 if (ngroups == NGROUPS_MAX) {
669                         fprintf(stderr,
670                                 _("%s: too many groups specified (max %d).\n"),
671                                 Prog, ngroups);
672                         break;
673                 }
674
675                 /*
676                  * Add the group name to the user's list of groups.
677                  */
678
679                 user_groups[ngroups++] = xstrdup(grp->gr_name);
680         } while (list);
681
682         user_groups[ngroups] = (char *) 0;
683
684         /*
685          * Any errors in finding group names are fatal
686          */
687
688         if (errors)
689                 return -1;
690
691         return 0;
692 }
693
694 /*
695  * usage - display usage message and exit
696  */
697
698 static void
699 usage(void)
700 {
701         fprintf(stderr,
702                 _("usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n"),
703                 Prog);
704         fprintf(stderr,
705                 _("\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n"));
706         fprintf(stderr, "\t\t");
707 #ifdef SHADOWPWD
708         fprintf(stderr, _("[-f inactive] [-e expire ] "));
709 #endif
710 #ifdef AUTH_METHODS
711         fprintf(stderr, _("[-A program] "));
712 #endif
713         fprintf(stderr, _("[-p passwd] name\n"));
714
715         fprintf(stderr, _("       %s\t-D [-g group] [-b base] [-s shell]\n"),
716                 Prog);
717 #ifdef SHADOWPWD
718         fprintf(stderr, _("\t\t[-f inactive] [-e expire ]\n"));
719 #endif
720
721         exit(E_USAGE);
722 }
723
724 /*
725  * new_pwent - initialize the values in a password file entry
726  *
727  *      new_pwent() takes all of the values that have been entered and
728  *      fills in a (struct passwd) with them.
729  */
730
731 static void
732 new_pwent(struct passwd *pwent)
733 {
734         memzero(pwent, sizeof *pwent);
735         pwent->pw_name = (char *) user_name;
736 #ifdef SHADOWPWD
737         if (is_shadow_pwd)
738                 pwent->pw_passwd = (char *) SHADOW_PASSWD_STRING;
739         else
740 #endif
741         pwent->pw_passwd = (char *) user_pass;
742
743 #ifdef ATT_AGE
744         pwent->pw_age = (char *) "";
745 #endif
746         pwent->pw_uid = user_id;
747         pwent->pw_gid = user_gid;
748         pwent->pw_gecos = (char *) user_comment;
749 #ifdef  ATT_COMMENT
750         pwent->pw_comment = (char *) "";
751 #endif
752 #ifdef BSD_QUOTA
753         pwent->pw_quota = (char *) "";
754 #endif
755         pwent->pw_dir = (char *) user_home;
756         pwent->pw_shell = (char *) user_shell;
757 }
758
759 #ifdef SHADOWPWD
760 static long
761 scale_age(long x)
762 {
763         if (x <= 0)
764                 return x;
765
766         return x * (DAY/SCALE);
767 }
768
769 /*
770  * new_spent - initialize the values in a shadow password file entry
771  *
772  *      new_spent() takes all of the values that have been entered and
773  *      fills in a (struct spwd) with them.
774  */
775
776 static void
777 new_spent(struct spwd *spent)
778 {
779         memzero(spent, sizeof *spent);
780         spent->sp_namp = (char *) user_name;
781         spent->sp_pwdp = (char *) user_pass;
782         spent->sp_lstchg = time((time_t *) 0) / SCALE;
783         spent->sp_min = scale_age(getdef_num("PASS_MIN_DAYS", -1));
784         spent->sp_max = scale_age(getdef_num("PASS_MAX_DAYS", -1));
785         spent->sp_warn = scale_age(getdef_num("PASS_WARN_AGE", -1));
786         spent->sp_inact = scale_age(def_inactive);
787         spent->sp_expire = scale_age(user_expire);
788         spent->sp_flag = -1;
789 }
790 #endif
791
792 /*
793  * grp_update - add user to secondary group set
794  *
795  *      grp_update() takes the secondary group set given in user_groups
796  *      and adds the user to each group given by that set.
797  */
798
799 static void
800 grp_update(void)
801 {
802         const struct group *grp;
803         struct group *ngrp;
804 #ifdef  SHADOWGRP
805         const struct sgrp *sgrp;
806         struct sgrp *nsgrp;
807 #endif
808
809         /*
810          * Lock and open the group file.  This will load all of the group
811          * entries.
812          */
813
814         if (! gr_lock ()) {
815                 fprintf(stderr, _("%s: error locking group file\n"), Prog);
816                 fail_exit(E_GRP_UPDATE);
817         }
818         if (! gr_open (O_RDWR)) {
819                 fprintf(stderr, _("%s: error opening group file\n"), Prog);
820                 fail_exit(E_GRP_UPDATE);
821         }
822 #ifdef  SHADOWGRP
823         if (is_shadow_grp && ! sgr_lock ()) {
824                 fprintf(stderr, _("%s: error locking shadow group file\n"),
825                         Prog);
826                 fail_exit(E_GRP_UPDATE);
827         }
828         if (is_shadow_grp && ! sgr_open (O_RDWR)) {
829                 fprintf(stderr, _("%s: error opening shadow group file\n"),
830                         Prog);
831                 fail_exit(E_GRP_UPDATE);
832         }
833 #endif
834
835         /*
836          * Scan through the entire group file looking for the groups that
837          * the user is a member of.
838          */
839
840         for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) {
841
842                 /*
843                  * See if the user specified this group as one of their
844                  * concurrent groups.
845                  */
846
847                 if (!is_on_list(user_groups, grp->gr_name))
848                         continue;
849
850                 /*
851                  * Make a copy - gr_update() will free() everything
852                  * from the old entry, and we need it later.
853                  */
854
855                 ngrp = __gr_dup(grp);
856                 if (!ngrp) {
857                         fail_exit(E_GRP_UPDATE);  /* XXX */
858                 }
859
860                 /* 
861                  * Add the username to the list of group members and
862                  * update the group entry to reflect the change.
863                  */
864
865                 ngrp->gr_mem = add_list (ngrp->gr_mem, user_name);
866                 if (!gr_update(ngrp)) {
867                         fprintf(stderr, "%s: error adding new group entry\n",
868                                 Prog);
869                         fail_exit(E_GRP_UPDATE);
870                 }
871 #ifdef  NDBM
872                 /*
873                  * Update the DBM group file with the new entry as well.
874                  */
875
876                 if (!gr_dbm_update(ngrp)) {
877                         fprintf(stderr, "%s: cannot add new dbm group entry\n",
878                                 Prog);
879                         fail_exit(E_GRP_UPDATE);
880                 } else
881                         gr_dbm_added++;
882 #endif
883                 SYSLOG((LOG_INFO, "add `%s' to group `%s'\n",
884                         user_name, ngrp->gr_name));
885         }
886 #ifdef NDBM
887         endgrent ();
888 #endif
889
890 #ifdef  SHADOWGRP
891         if (!is_shadow_grp)
892                 return;
893
894         /*
895          * Scan through the entire shadow group file looking for the groups
896          * that the user is a member of.  The administrative list isn't
897          * modified.
898          */
899
900         for (sgr_rewind (), sgrp = sgr_next ();sgrp;sgrp = sgr_next ()) {
901
902                 /*
903                  * See if the user specified this group as one of their
904                  * concurrent groups.
905                  */
906
907                 if (!gr_locate(sgrp->sg_name))
908                         continue;
909
910                 if (!is_on_list(user_groups, sgrp->sg_name))
911                         continue;
912
913                 /*
914                  * Make a copy - sgr_update() will free() everything
915                  * from the old entry, and we need it later.
916                  */
917
918                 nsgrp = __sgr_dup(sgrp);
919                 if (!nsgrp) {
920                         fail_exit(E_GRP_UPDATE);  /* XXX */
921                 }
922
923                 /* 
924                  * Add the username to the list of group members and
925                  * update the group entry to reflect the change.
926                  */
927
928                 nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_name);
929                 if (!sgr_update(nsgrp)) {
930                         fprintf(stderr,
931                                 _("%s: error adding new group entry\n"),
932                                 Prog);
933                         fail_exit(E_GRP_UPDATE);
934                 }
935 #ifdef  NDBM
936                 /*
937                  * Update the DBM group file with the new entry as well.
938                  */
939
940                 if (!sg_dbm_update(nsgrp)) {
941                         fprintf(stderr,
942                                 _("%s: cannot add new dbm group entry\n"),
943                                 Prog);
944                         fail_exit(E_GRP_UPDATE);
945                 } else
946                         sg_dbm_added++;
947 #endif  /* NDBM */
948                 SYSLOG((LOG_INFO, "add `%s' to shadow group `%s'\n",
949                         user_name, nsgrp->sg_name));
950         }
951 #ifdef NDBM
952         endsgent ();
953 #endif  /* NDBM */
954 #endif  /* SHADOWGRP */
955 }
956
957 /*
958  * find_new_uid - find the next available UID
959  *
960  *      find_new_uid() locates the next highest unused UID in the password
961  *      file, or checks the given user ID against the existing ones for
962  *      uniqueness.
963  */
964
965 static void
966 find_new_uid(void)
967 {
968         const struct passwd *pwd;
969         uid_t uid_min, uid_max;
970
971         uid_min = getdef_num("UID_MIN", 100);
972         uid_max = getdef_num("UID_MAX", 60000);
973
974         /*
975          * Start with some UID value if the user didn't provide us with
976          * one already.
977          */
978
979         if (! uflg)
980                 user_id = uid_min;
981
982         /*
983          * Search the entire password file, either looking for this
984          * UID (if the user specified one with -u) or looking for the
985          * largest unused value.
986          */
987
988 #ifdef NO_GETPWENT
989         pw_rewind();
990         while ((pwd = pw_next())) {
991 #else  /* using getpwent() we can check against NIS users etc.  */
992         setpwent();
993         while ((pwd = getpwent())) {
994 #endif
995                 if (strcmp(user_name, pwd->pw_name) == 0) {
996                         fprintf(stderr, _("%s: name %s is not unique\n"),
997                                 Prog, user_name);
998                         exit(E_NAME_IN_USE);
999                 }
1000                 if (uflg && user_id == pwd->pw_uid) {
1001                         fprintf(stderr, _("%s: uid %d is not unique\n"),
1002                                 Prog, (int) user_id);
1003                         exit(E_UID_IN_USE);
1004                 }
1005                 if (! uflg && pwd->pw_uid >= user_id) {
1006                         if (pwd->pw_uid > uid_max)
1007                                 continue;
1008                         user_id = pwd->pw_uid + 1;
1009                 }
1010         }
1011         /*
1012          * If a user with uid equal to UID_MAX exists, the above algorithm
1013          * will give us UID_MAX+1 even if not unique.  Search for the first
1014          * free uid starting with UID_MIN (it's O(n*n) but can be avoided
1015          * by not having users with uid equal to UID_MAX).  --marekm
1016          */
1017         if (!uflg && user_id == uid_max + 1) {
1018                 for (user_id = uid_min; user_id < uid_max; user_id++) {
1019 #ifdef NO_GETPWENT
1020                         pw_rewind();
1021                         while ((pwd = pw_next()) && pwd->pw_uid != user_id)
1022                                 ;
1023                         if (!pwd)
1024                                 break;
1025 #else
1026                         if (!getpwuid(user_id))
1027                                 break;
1028 #endif
1029                 }
1030                 if (user_id == uid_max) {
1031                         fprintf(stderr, _("%s: can't get unique uid\n"),
1032                                 Prog);
1033                         fail_exit(E_UID_IN_USE);
1034                 }
1035         }
1036 }
1037
1038 #ifdef AUTH_METHODS
1039 /*
1040  * convert_auth - convert the argument list to a authentication list
1041  */
1042
1043 static void
1044 convert_auth(char *auths, const char *list)
1045 {
1046         char    *cp, *end;
1047         char    buf[257];
1048
1049         /*
1050          * Copy each method.  DEFAULT is replaced by an encrypted string
1051          * if one can be found in the current authentication list.
1052          */
1053
1054         strcpy(buf, list);
1055         auths[0] = '\0';
1056         for (cp = buf; cp; cp = end) {
1057                 if (auths[0])
1058                         strcat(auths, ";");
1059
1060                 if ((end = strchr(cp, ',')))
1061                         *end++ = '\0';
1062
1063                 if (strcmp(cp, "DEFAULT") == 0) {
1064                         strcat(auths, user_pass);
1065                 } else {
1066                         strcat(auths, "@");
1067                         strcat(auths, cp);
1068                 }
1069         }
1070 }
1071
1072 /*
1073  * valid_auth - check authentication list for validity
1074  */
1075
1076 static int
1077 valid_auth(const char *methods)
1078 {
1079         char    *cp, *end;
1080         char    buf[257];
1081         int     default_cnt = 0;
1082
1083         /*
1084          * Cursory checks, length and illegal characters
1085          */
1086
1087         if ((int) strlen (methods) > 256)
1088                 return 0;
1089
1090         if (! VALID (methods))
1091                 return 0;
1092
1093         /*
1094          * Pick each method apart and check it.
1095          */
1096
1097         strcpy (buf, methods);
1098         for (cp = buf;cp;cp = end) {
1099                 if ((end = strchr (cp, ',')))
1100                         *end++ = '\0';
1101
1102                 if (strcmp (cp, "DEFAULT") == 0) {
1103                         if (default_cnt++ > 0)
1104                                 return 0;
1105                 }
1106         }
1107         return 1;
1108 }
1109 #endif  /* AUTH_METHODS */
1110
1111 /*
1112  * process_flags - perform command line argument setting
1113  *
1114  *      process_flags() interprets the command line arguments and sets
1115  *      the values that the user will be created with accordingly.  The
1116  *      values are checked for sanity.
1117  */
1118
1119 static void
1120 process_flags(int argc, char **argv)
1121 {
1122         const struct group *grp;
1123         int anyflag = 0;
1124         int arg;
1125         char *cp;
1126
1127 #ifdef SHADOWPWD
1128 #define FLAGS "A:Du:og:G:d:s:c:mk:p:f:e:b:O:M"
1129 #else
1130 #define FLAGS "A:Du:og:G:d:s:c:mk:p:b:O:M"
1131 #endif
1132         while ((arg = getopt(argc, argv, FLAGS)) != EOF) {
1133 #undef FLAGS
1134                 switch (arg) {
1135 #ifdef AUTH_METHODS
1136                 case 'A':
1137                         if (! valid_auth (optarg)) {
1138                                 fprintf(stderr,
1139                                         _("%s: invalid field `%s'\n"),
1140                                         Prog, optarg);
1141                                 exit(E_BAD_ARG);
1142                         }
1143                         auth_arg = optarg;
1144                         Aflg++;
1145                         break;
1146 #endif
1147                 case 'b':
1148                         if (!Dflg)
1149                                 usage ();
1150
1151                         if (!VALID(optarg) || optarg[0] != '/') {
1152                                 fprintf(stderr,
1153                                         _("%s: invalid base directory `%s'\n"),
1154                                         Prog, optarg);
1155                                 exit(E_BAD_ARG);
1156                         }
1157                         def_home = optarg;
1158                         bflg++;
1159                         break;
1160                 case 'c':
1161                         if (!VALID(optarg)) {
1162                                 fprintf(stderr,
1163                                         _("%s: invalid comment `%s'\n"),
1164                                         Prog, optarg);
1165                                 exit(E_BAD_ARG);
1166                         }
1167                         user_comment = optarg;
1168                         cflg++;
1169                         break;
1170                 case 'd':
1171                         if (!VALID(optarg) || optarg[0] != '/') {
1172                                 fprintf(stderr,
1173                                         _("%s: invalid home directory `%s'\n"),
1174                                         Prog, optarg);
1175                                 exit(E_BAD_ARG);
1176                         }
1177                         user_home = optarg;
1178                         dflg++;
1179                         break;
1180                 case 'D':
1181                         if (anyflag)
1182                                 usage();
1183                         Dflg++;
1184                         break;
1185 #ifdef SHADOWPWD
1186                 case 'e':
1187                         if (*optarg) {
1188                                 user_expire = strtoday(optarg);
1189                                 if (user_expire == -1) {
1190                                         fprintf(stderr,
1191                                                 _("%s: invalid date `%s'\n"),
1192                                                 Prog, optarg);
1193                                         exit(E_BAD_ARG);
1194                                 }
1195                         } else
1196                                 user_expire = -1;
1197
1198                         /*
1199                          * -e "" is allowed - it's a no-op without /etc/shadow
1200                          */
1201                         if (*optarg && !is_shadow_pwd) {
1202                                 fprintf(stderr,
1203                                         _("%s: shadow passwords required for -e\n"),
1204                                         Prog);
1205                                 exit(E_USAGE);
1206                         }
1207                         if (Dflg)
1208                                 def_expire = optarg;
1209                         eflg++;
1210                         break;
1211                 case 'f':
1212                         def_inactive = get_number(optarg);
1213                         /*
1214                          * -f -1 is allowed - it's a no-op without /etc/shadow
1215                          */
1216                         if (def_inactive != -1 && !is_shadow_pwd) {
1217                                 fprintf(stderr,
1218                                         _("%s: shadow passwords required for -f\n"),
1219                                         Prog);
1220                                 exit(E_USAGE);
1221                         }
1222                         fflg++;
1223                         break;
1224 #endif
1225                 case 'g':
1226                         grp = getgr_nam_gid(optarg);
1227                         if (!grp) {
1228                                 fprintf(stderr, _("%s: unknown group %s\n"),
1229                                         Prog, optarg);
1230                                 exit(E_NOTFOUND);
1231                         }
1232                         if (Dflg) {
1233                                 def_group = grp->gr_gid;
1234                                 def_gname = optarg;
1235                         } else {
1236                                 user_gid = grp->gr_gid;
1237                         }
1238                         gflg++;
1239                         break;
1240                 case 'G':
1241                         if (get_groups(optarg))
1242                                 exit(E_NOTFOUND);
1243                         if (user_groups[0])
1244                                 do_grp_update++;
1245                         Gflg++;
1246                         break;
1247                 case 'k':
1248                         def_template = optarg;
1249                         kflg++;
1250                         break;
1251                 case 'm':
1252                         mflg++;
1253                         break;
1254                 case 'M':
1255                         /*
1256                          * don't create home dir - this is the default,
1257                          * ignored for RedHat/PLD adduser compatibility.
1258                          */
1259                         break;
1260                 case 'o':
1261                         oflg++;
1262                         break;
1263                 case 'O':
1264                         /*
1265                          * override login.defs defaults (-O name=value)
1266                          * example: -O UID_MIN=100 -O UID_MAX=499
1267                          * note: -O UID_MIN=10,UID_MAX=499 doesn't work yet
1268                          */
1269                         cp = strchr(optarg, '=');
1270                         if (!cp) {
1271                                 fprintf(stderr,
1272                                         _("%s: -O requires NAME=VALUE\n"),
1273                                         Prog);
1274                                 exit(E_BAD_ARG);
1275                         }
1276                         /* terminate name, point to value */
1277                         *cp++ = '\0';
1278                         if (putdef_str(optarg, cp) < 0)
1279                                 exit(E_BAD_ARG);
1280                         break;
1281                 case 'p':  /* set encrypted password */
1282                         if (!VALID(optarg)) {
1283                                 fprintf(stderr, _("%s: invalid field `%s'\n"),
1284                                         Prog, optarg);
1285                                 exit(E_BAD_ARG);
1286                         }
1287                         user_pass = optarg;
1288                         break;
1289                 case 's':
1290                         if (!VALID(optarg) || (optarg[0] &&
1291                             (optarg[0] != '/' && optarg[0] != '*'))) {
1292                                 fprintf(stderr, _("%s: invalid shell `%s'\n"),
1293                                         Prog, optarg);
1294                                 exit(E_BAD_ARG);
1295                         }
1296                         user_shell = optarg;
1297                         def_shell = optarg;
1298                         sflg++;
1299                         break;
1300                 case 'u':
1301                         user_id = get_number(optarg);
1302                         uflg++;
1303                         break;
1304                 default:
1305                         usage();
1306                 }
1307                 anyflag++;
1308         }
1309
1310         /*
1311          * Certain options are only valid in combination with others.
1312          * Check it here so that they can be specified in any order.
1313          */
1314         if ((oflg && !uflg) || (kflg && !mflg))
1315                 usage();
1316
1317         /*
1318          * Either -D or username is required.  Defaults can be set with -D
1319          * for the -b, -e, -f, -g, -s options only.
1320          */
1321         if (Dflg) {
1322                 if (optind != argc)
1323                         usage();
1324
1325                 if (uflg || oflg || Gflg || dflg || cflg || mflg)
1326                         usage();
1327         } else {
1328                 if (optind != argc - 1)
1329                         usage();
1330
1331                 user_name = argv[optind];
1332                 if (!check_user_name(user_name)) {
1333                         fprintf(stderr, _("%s: invalid user name `%s'\n"),
1334                                 Prog, user_name);
1335                         exit(E_BAD_ARG);
1336                 }
1337                 if (!dflg) {
1338                         char *uh;
1339
1340                         uh = xmalloc(strlen(def_home) + strlen(user_name) + 2);
1341                         sprintf(uh, "%s/%s", def_home, user_name);
1342                         user_home = uh;
1343                 }
1344         }
1345
1346 #ifdef SHADOWPWD
1347         if (!eflg)
1348                 user_expire = strtoday(def_expire);
1349 #endif
1350
1351         if (!gflg)
1352                 user_gid = def_group;
1353
1354         if (!sflg)
1355                 user_shell = def_shell;
1356 }
1357
1358 /*
1359  * close_files - close all of the files that were opened
1360  *
1361  *      close_files() closes all of the files that were opened for this
1362  *      new user.  This causes any modified entries to be written out.
1363  */
1364
1365 static void
1366 close_files(void)
1367 {
1368         if (!pw_close()) {
1369                 fprintf(stderr, _("%s: cannot rewrite password file\n"), Prog);
1370                 fail_exit(E_PW_UPDATE);
1371         }
1372 #ifdef  SHADOWPWD
1373         if (is_shadow_pwd && !spw_close()) {
1374                 fprintf(stderr, _("%s: cannot rewrite shadow password file\n"),
1375                         Prog);
1376                 fail_exit(E_PW_UPDATE);
1377         }
1378 #endif
1379         if (do_grp_update) {
1380                 if (!gr_close()) {
1381                         fprintf(stderr, _("%s: cannot rewrite group file\n"),
1382                                 Prog);
1383                         fail_exit(E_GRP_UPDATE);
1384                 }
1385                 gr_unlock();
1386 #ifdef  SHADOWGRP
1387                 if (is_shadow_grp && !sgr_close()) {
1388                         fprintf (stderr,
1389                                 _("%s: cannot rewrite shadow group file\n"),
1390                                 Prog);
1391                         fail_exit(E_GRP_UPDATE);
1392                 }
1393                 if (is_shadow_grp)
1394                         sgr_unlock();
1395 #endif
1396         }
1397 #ifdef  SHADOWPWD
1398         if (is_shadow_pwd)
1399                 spw_unlock();
1400 #endif
1401         pw_unlock();
1402 }
1403
1404 /*
1405  * open_files - lock and open the password files
1406  *
1407  *      open_files() opens the two password files.
1408  */
1409
1410 static void
1411 open_files(void)
1412 {
1413         if (!pw_lock()) {
1414                 fprintf(stderr, _("%s: unable to lock password file\n"), Prog);
1415                 exit(E_PW_UPDATE);
1416         }
1417         if (!pw_open(O_RDWR)) {
1418                 fprintf(stderr, _("%s: unable to open password file\n"), Prog);
1419                 pw_unlock();
1420                 exit(E_PW_UPDATE);
1421         }
1422 #ifdef  SHADOWPWD
1423         if (is_shadow_pwd && !spw_lock()) {
1424                 fprintf(stderr, _("%s: cannot lock shadow password file\n"),
1425                         Prog);
1426                 pw_unlock();
1427                 exit(E_PW_UPDATE);
1428         }
1429         if (is_shadow_pwd && !spw_open(O_RDWR)) {
1430                 fprintf(stderr, _("%s: cannot open shadow password file\n"),
1431                         Prog);
1432                 spw_unlock();
1433                 pw_unlock();
1434                 exit(E_PW_UPDATE);
1435         }
1436 #endif
1437 }
1438
1439
1440 static void
1441 faillog_reset(uid_t uid)
1442 {
1443         struct faillog fl;
1444         int fd;
1445
1446         fd = open(FAILLOG_FILE, O_RDWR);
1447         if (fd >= 0) {
1448                 memzero(&fl, sizeof(fl));
1449                 lseek(fd, (off_t) sizeof(fl) * uid, SEEK_SET);
1450                 write(fd, &fl, sizeof(fl));
1451                 close(fd);
1452         }
1453 }
1454
1455 static void
1456 lastlog_reset(uid_t uid)
1457 {
1458         struct lastlog ll;
1459         int fd;
1460
1461         fd = open(LASTLOG_FILE, O_RDWR);
1462         if (fd >= 0) {
1463                 memzero(&ll, sizeof(ll));
1464                 lseek(fd, (off_t) sizeof(ll) * uid, SEEK_SET);
1465                 write(fd, &ll, sizeof(ll));
1466                 close(fd);
1467         }
1468 }
1469
1470 /*
1471  * usr_update - create the user entries
1472  *
1473  *      usr_update() creates the password file entries for this user
1474  *      and will update the group entries if required.
1475  */
1476
1477 static void
1478 usr_update(void)
1479 {
1480         struct  passwd  pwent;
1481 #ifdef  SHADOWPWD
1482         struct  spwd    spent;
1483 #endif
1484
1485         if (! oflg)
1486                 find_new_uid ();
1487
1488 #ifdef AUTH_METHODS
1489         if (Aflg) {
1490                 convert_auth(user_auth, auth_arg);
1491                 user_pass = user_auth;
1492         }
1493 #endif
1494
1495         /*
1496          * Fill in the password structure with any new fields, making
1497          * copies of strings.
1498          */
1499
1500         new_pwent (&pwent);
1501 #ifdef  SHADOWPWD
1502         new_spent (&spent);
1503 #endif
1504
1505         /*
1506          * Create a syslog entry.  We need to do this now in case anything
1507          * happens so we know what we were trying to accomplish.
1508          */
1509
1510 #ifdef AUTH_METHODS
1511         SYSLOG((LOG_INFO,
1512             "new user: name=%s, uid=%d, gid=%d, home=%s, shell=%s, auth=%s\n",
1513                 user_name, user_id, user_gid, user_home, user_shell,
1514                 Aflg ? auth_arg : "DEFAULT"));
1515 #else
1516         SYSLOG((LOG_INFO,
1517                 "new user: name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",
1518                 user_name, user_id, user_gid, user_home, user_shell));
1519 #endif
1520
1521 #ifdef AUTH_METHODS
1522         /*
1523          * Attempt to add the new user to any authentication programs
1524          * which have been requested.  Since this is more likely to fail
1525          * than the update of the password file, we do this first.
1526          */
1527
1528         if (Aflg && pw_auth(user_auth, pwent.pw_name, PW_ADD, (char *) 0)) {
1529                 fprintf(stderr, _("%s: error adding authentication method\n"),
1530                         Prog);
1531                 fail_exit(E_PW_UPDATE);  /* XXX */
1532         }
1533 #endif  /* AUTH_METHODS */
1534
1535         /*
1536          * Initialize faillog and lastlog entries for this UID in case
1537          * it belongs to a previously deleted user.  We do it only if
1538          * no user with this UID exists yet (entries for shared UIDs
1539          * are left unchanged).  --marekm
1540          */
1541
1542         if (!getpwuid(user_id)) {
1543                 faillog_reset(user_id);
1544                 lastlog_reset(user_id);
1545         }
1546
1547         /*
1548          * Put the new (struct passwd) in the table.
1549          */
1550
1551         if (! pw_update (&pwent)) {
1552                 fprintf(stderr, _("%s: error adding new password entry\n"),
1553                         Prog);
1554                 exit(E_PW_UPDATE);
1555         }
1556
1557 #ifdef NDBM
1558         /*
1559          * Update the DBM files.  This creates the user before the flat
1560          * files are updated.  This is safe before the password field is
1561          * either locked, or set to a valid authentication string.
1562          */
1563
1564         if (pw_dbm_present()) {
1565                 if (!pw_dbm_update(&pwent)) {
1566                         fprintf(stderr,
1567                                 _("%s: error updating password dbm entry\n"),
1568                                 Prog);
1569                         exit(E_PW_UPDATE);
1570                 } else
1571                         pw_dbm_added = 1;
1572         }
1573         endpwent();
1574 #endif
1575
1576 #ifdef  SHADOWPWD
1577         /*
1578          * Put the new (struct spwd) in the table.
1579          */
1580
1581         if (is_shadow_pwd && !spw_update(&spent)) {
1582                 fprintf(stderr,
1583                         _("%s: error adding new shadow password entry\n"),
1584                         Prog);
1585                 exit(E_PW_UPDATE);
1586         }
1587
1588 #ifdef  NDBM
1589         /* 
1590          * Update the DBM files for the shadow password.  This entry is
1591          * output before the entry in the flat file, but this is safe as
1592          * the password is locked or the authentication string has the
1593          * proper values.
1594          */
1595
1596         if (is_shadow_pwd && sp_dbm_present()) {
1597                 if (!sp_dbm_update(&spent)) {
1598                         fprintf(stderr,
1599                                 _("%s: error updating shadow passwd dbm entry\n"),
1600                                 Prog);
1601                         fail_exit(E_PW_UPDATE);
1602                 } else
1603                         sp_dbm_added++;
1604                 endspent();
1605         }
1606 #endif
1607 #endif  /* SHADOWPWD */
1608
1609         /*
1610          * Do any group file updates for this user.
1611          */
1612
1613         if (do_grp_update)
1614                 grp_update();
1615 }
1616
1617 /*
1618  * create_home - create the user's home directory
1619  *
1620  *      create_home() creates the user's home directory if it does not
1621  *      already exist.  It will be created mode 755 owned by the user
1622  *      with the user's default group.
1623  */
1624
1625 static void
1626 create_home(void)
1627 {
1628         if (access(user_home, F_OK)) {
1629                 /* XXX - create missing parent directories.  --marekm */
1630                 if (mkdir (user_home, 0)) {
1631                         fprintf(stderr, _("%s: cannot create directory %s\n"),
1632                                 Prog, user_home);
1633                         fail_exit(E_HOMEDIR);
1634                 }
1635                 chown (user_home, user_id, user_gid);
1636 #if 1
1637                 chmod(user_home, 0777 & ~getdef_num("UMASK", 077));
1638 #else
1639                 chmod (user_home, 0755);
1640 #endif
1641                 home_added++;
1642         }
1643 }
1644
1645 /*
1646  * main - useradd command
1647  */
1648
1649 int
1650 main(int argc, char **argv)
1651 {
1652         /*
1653          * Get my name so that I can use it to report errors.
1654          */
1655
1656         Prog = Basename(argv[0]);
1657
1658         setlocale(LC_ALL, "");
1659         bindtextdomain(PACKAGE, LOCALEDIR);
1660         textdomain(PACKAGE);
1661
1662         openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
1663
1664 #ifdef SHADOWPWD
1665         is_shadow_pwd = spw_file_present();
1666 #endif
1667 #ifdef SHADOWGRP
1668         is_shadow_grp = sgr_file_present();
1669 #endif
1670
1671         /*
1672          * The open routines for the NDBM files don't use read-write
1673          * as the mode, so we have to clue them in.
1674          */
1675
1676 #ifdef  NDBM
1677         pw_dbm_mode = O_RDWR;
1678 #ifdef  SHADOWPWD
1679         sp_dbm_mode = O_RDWR;
1680 #endif
1681         gr_dbm_mode = O_RDWR;
1682 #ifdef  SHADOWGRP
1683         sg_dbm_mode = O_RDWR;
1684 #endif
1685 #endif
1686         get_defaults();
1687
1688         process_flags(argc, argv);
1689
1690         /*
1691          * See if we are messing with the defaults file, or creating
1692          * a new user.
1693          */
1694
1695         if (Dflg) {
1696                 if (gflg || bflg || fflg || eflg || sflg)
1697                         exit (set_defaults () ? 1:0);
1698
1699                 show_defaults();
1700                 exit(E_SUCCESS);
1701         }
1702
1703         /*
1704          * Start with a quick check to see if the user exists.
1705          */
1706
1707         if (getpwnam(user_name)) {
1708                 fprintf(stderr, _("%s: user %s exists\n"), Prog, user_name);
1709                 exit(E_NAME_IN_USE);
1710         }
1711
1712         /*
1713          * Do the hard stuff - open the files, create the user entries,
1714          * create the home directory, then close and update the files.
1715          */
1716
1717         open_files ();
1718
1719         usr_update ();
1720
1721         if (mflg) {
1722                 create_home ();
1723                 copy_tree (def_template, user_home, user_id, user_gid);
1724         } else if (getdef_str("CREATE_HOME")) {
1725                 /*
1726                  * RedHat added the CREATE_HOME option in login.defs in their
1727                  * version of shadow-utils (which makes -m the default, with
1728                  * new -M option to turn it off).  Unfortunately, this
1729                  * changes the way useradd works (it can be run by scripts
1730                  * expecting some standard behaviour), compared to other
1731                  * Unices and other Linux distributions, and also adds a lot
1732                  * of confusion :-(.
1733                  * So we now recognize CREATE_HOME and give a warning here
1734                  * (better than "configuration error ... notify administrator"
1735                  * errors in every program that reads /etc/login.defs).  -MM
1736                  */
1737                 fprintf(stderr,
1738         _("%s: warning: CREATE_HOME not supported, please use -m instead.\n"),
1739                         Prog);
1740         }
1741
1742         close_files ();
1743         exit(E_SUCCESS);
1744         /*NOTREACHED*/
1745 }