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.
23 #include <sys/param.h>
25 #include <sys/types.h>
30 /* structs __________________________ */
37 /* data _____________________________ */
39 /* defaults : should this be in an external file? */
40 static const char default_passwd[] = "x";
41 static const char default_gecos[] = "Linux User,,,";
42 static const char default_home_prefix[] = "/home";
44 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
46 static int shadow_enabled = 0;
50 /* EDR recoded such that the uid may be passed in *p */
51 static int passwd_study(const char *filename, struct passwd *p)
57 const int max = 65000;
59 passwd = bb_wfopen(filename, "r");
63 /* EDR if uid is out of bounds, set to min */
64 if ((p->pw_uid > max) || (p->pw_uid < min))
68 * make sure login isn't taken;
69 * find free uid and gid;
71 while ((pw = fgetpwent(passwd))) {
72 if (strcmp(pw->pw_name, p->pw_name) == 0) {
76 if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max)
77 && (pw->pw_uid >= min)) {
78 p->pw_uid = pw->pw_uid + 1;
83 /* EDR check for an already existing gid */
84 while (getgrgid(p->pw_uid) != NULL)
87 /* EDR also check for an existing group definition */
88 if (getgrnam(p->pw_name) != NULL)
91 /* EDR create new gid always = uid */
92 p->pw_gid = p->pw_uid;
95 /* EDR bounds check */
96 if ((p->pw_uid > max) || (p->pw_uid < min))
103 static void addgroup_wrapper(const char *login, gid_t gid)
107 cmd = bb_xasprintf("addgroup -g %d \"%s\"", gid, login);
112 static void passwd_wrapper(const char *login) ATTRIBUTE_NORETURN;
114 static void passwd_wrapper(const char *login)
116 static const char prog[] = "passwd";
117 execlp(prog, prog, login, NULL);
118 bb_error_msg_and_die("Failed to execute '%s', you must set the password for '%s' manually", prog, login);
121 /* putpwent(3) remix */
122 static int adduser(const char *filename, struct passwd *p, int makehome, int setpass)
126 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
132 /* if using a pre-existing group, don't create one */
136 /* make sure everything is kosher and setup uid && gid */
137 passwd = bb_wfopen(filename, "a");
138 if (passwd == NULL) {
141 fseek(passwd, 0, SEEK_END);
143 /* if (passwd_study(filename, p) == 0) { */
144 r = passwd_study(filename, p);
147 bb_error_msg("%s: login already in use", p->pw_name);
149 bb_error_msg("illegal uid or no uids left");
151 bb_error_msg("group name %s already in use", p->pw_name);
153 bb_error_msg("generic error.");
158 if (putpwent(p, passwd) == -1) {
163 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
164 /* add to shadow if necessary */
165 if (shadow_enabled) {
166 shadow = bb_wfopen(bb_path_shadow_file, "a");
167 if (shadow == NULL) {
170 fseek(shadow, 0, SEEK_END);
172 sp->sp_max = 99999; /* debianish */
174 fprintf(shadow, "%s:!:%ld:%ld:%ld:%ld:::\n",
175 sp->sp_namp, sp->sp_lstchg, sp->sp_min, sp->sp_max,
183 /* addgroup should be responsible for dealing w/ gshadow */
184 addgroup_wrapper(p->pw_name, p->pw_gid);
187 /* Clear the umask for this process so it doesn't
188 * * screw up the permissions on the mkdir and chown. */
193 if (mkdir(p->pw_dir, 0755)) {
194 bb_perror_msg("%s", p->pw_dir);
196 /* Set the owner and group so it is owned by the new user. */
197 if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) {
198 bb_perror_msg("%s", p->pw_dir);
200 /* Now fix up the permissions to 2755. Can't do it before now
201 * since chown will clear the setgid bit */
202 if (chmod(p->pw_dir, 02755)) {
203 bb_perror_msg("%s", p->pw_dir);
208 /* interactively set passwd */
209 passwd_wrapper(p->pw_name);
216 /* return current uid (root is always uid == 0, right?) */
217 #ifndef CONFIG_ADDGROUP
218 static inline void if_i_am_not_root(void)
220 void if_i_am_not_root(void)
224 bb_error_msg_and_die( "Only root may add a user or group to the system.");
228 #define SETPASS (1 << 4)
229 #define MAKEHOME (1 << 6)
232 * adduser will take a login_name as its first parameter.
238 * can be customized via command-line parameters.
239 * ________________________________________________________________________ */
240 int adduser_main(int argc, char **argv)
244 const char *gecos = default_gecos;
245 const char *home = NULL;
246 const char *shell = DEFAULT_SHELL;
247 const char *usegroup = NULL;
257 flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &home, &gecos, &shell, &usegroup);
259 if (flags & SETPASS) {
262 if (flags & MAKEHOME) {
270 if (optind >= argc) {
271 bb_error_msg_and_die( "no user specified");
273 login = argv[optind];
275 /* create string for $HOME if not specified already */
277 home = concat_path_file(default_home_prefix, login);
279 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
280 /* is /etc/shadow in use? */
281 shadow_enabled = (0 == access(bb_path_shadow_file, F_OK));
284 /* create a passwd struct */
285 pw.pw_name = (char *)login;
286 pw.pw_passwd = (char *)default_passwd;
289 pw.pw_gecos = (char *)gecos;
290 pw.pw_dir = (char *)home;
291 pw.pw_shell = (char *)shell;
294 /* Add user to a group that already exists */
295 pw.pw_gid = bb_xgetgrnam(usegroup);
300 return adduser(bb_path_passwd_file, &pw, makehome, setpass);