1 /* vi: set sw=4 ts=4: */
3 * adduser - add users to /etc/passwd and /etc/shadow
5 * Copyright (C) 1999 by Lineo, inc. and John Beppu
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
13 #define OPT_DONT_SET_PASS (1 << 4)
14 #define OPT_SYSTEM_ACCOUNT (1 << 5)
15 #define OPT_DONT_MAKE_HOME (1 << 6)
19 /* recoded such that the uid may be passed in *p */
20 static void passwd_study(struct passwd *p)
24 if (getpwnam(p->pw_name))
25 bb_error_msg_and_die("login '%s' is in use", p->pw_name);
27 if (option_mask32 & OPT_SYSTEM_ACCOUNT) {
35 /* check for a free uid (and maybe gid) */
36 while (getpwuid(p->pw_uid) || (!p->pw_gid && getgrgid(p->pw_uid)))
41 p->pw_gid = p->pw_uid;
42 if (getgrnam(p->pw_name))
43 bb_error_msg_and_die("group name '%s' is in use", p->pw_name);
47 bb_error_msg_and_die("no free uids left");
50 static void addgroup_wrapper(struct passwd *p)
54 cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name);
59 static void passwd_wrapper(const char *login) ATTRIBUTE_NORETURN;
61 static void passwd_wrapper(const char *login)
63 static const char prog[] ALIGN1 = "passwd";
65 BB_EXECLP(prog, prog, login, NULL);
66 bb_error_msg_and_die("cannot execute %s, you must set password manually", prog);
70 * adduser will take a login_name as its first parameter.
72 * can be customized via command-line parameters.
74 int adduser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
75 int adduser_main(int argc, char **argv)
78 const char *usegroup = NULL;
83 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
86 pw.pw_gecos = (char *)"Linux User,,,";
87 pw.pw_shell = (char *)DEFAULT_SHELL;
90 /* exactly one non-option arg */
91 opt_complementary = "=1";
92 getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
95 /* fill in the passwd struct */
98 /* create string for $HOME if not specified already */
99 pw.pw_dir = xasprintf("/home/%s", argv[0]);
101 pw.pw_passwd = (char *)"x";
102 pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */
104 /* make sure everything is kosher and setup uid && maybe gid */
108 file = xfopen(bb_path_passwd_file, "a");
109 //fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
110 if (putpwent(&pw, file) != 0) {
111 bb_perror_nomsg_and_die();
113 /* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
114 * We will exec passwd, files must be flushed & closed before that! */
117 #if ENABLE_FEATURE_SHADOWPASSWDS
118 /* add to shadow if necessary */
119 file = fopen_or_warn(bb_path_shadow_file, "a");
121 //fseek(file, 0, SEEK_END);
122 fprintf(file, "%s:!:%u:0:99999:7:::\n",
123 pw.pw_name, /* username */
124 (unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
125 /*0,*/ /* sp->sp_min */
126 /*99999,*/ /* sp->sp_max */
127 /*7*/ /* sp->sp_warn */
134 /* addgroup should be responsible for dealing w/ gshadow */
135 /* if using a pre-existing group, don't create one */
137 addgroup_wrapper(&pw);
139 /* Clear the umask for this process so it doesn't
140 * screw up the permissions on the mkdir and chown. */
142 if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
143 /* Set the owner and group so it is owned by the new user,
144 then fix up the permissions to 2755. Can't do it before
145 since chown will clear the setgid bit */
146 if (mkdir(pw.pw_dir, 0755)
147 || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid)
148 || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */
150 bb_simple_perror_msg(pw.pw_dir);
154 if (!(option_mask32 & OPT_DONT_SET_PASS)) {
155 /* interactively set passwd */
156 passwd_wrapper(pw.pw_name);