Tomato 1.28
[tomato.git] / release / src / router / busybox / loginutils / adduser.c
blob8a5d902e6bb6bd51c1015cfaf2e2f413148b3d5c
1 /* vi: set sw=4 ts=4: */
2 /*
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.
9 */
10 #include "libbb.h"
12 #define OPT_DONT_SET_PASS (1 << 4)
13 #define OPT_SYSTEM_ACCOUNT (1 << 5)
14 #define OPT_DONT_MAKE_HOME (1 << 6)
16 /* remix */
17 /* recoded such that the uid may be passed in *p */
18 static void passwd_study(struct passwd *p)
20 int max;
22 if (getpwnam(p->pw_name))
23 bb_error_msg_and_die("login '%s' is in use", p->pw_name);
25 if (option_mask32 & OPT_SYSTEM_ACCOUNT) {
26 p->pw_uid = 0;
27 max = 999;
28 } else {
29 p->pw_uid = 1000;
30 max = 64999;
33 /* check for a free uid (and maybe gid) */
34 while (getpwuid(p->pw_uid) || (p->pw_gid == (gid_t)-1 && getgrgid(p->pw_uid))) {
35 p->pw_uid++;
36 if (p->pw_uid > max)
37 bb_error_msg_and_die("no free uids left");
40 if (p->pw_gid == (gid_t)-1) {
41 p->pw_gid = p->pw_uid; /* new gid = uid */
42 if (getgrnam(p->pw_name))
43 bb_error_msg_and_die("group name '%s' is in use", p->pw_name);
47 static void addgroup_wrapper(struct passwd *p)
49 char *cmd;
51 cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name);
52 system(cmd);
53 free(cmd);
56 static void passwd_wrapper(const char *login) NORETURN;
58 static void passwd_wrapper(const char *login)
60 static const char prog[] ALIGN1 = "passwd";
62 BB_EXECLP(prog, prog, login, NULL);
63 bb_error_msg_and_die("cannot execute %s, you must set password manually", prog);
66 #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
67 static const char adduser_longopts[] ALIGN1 =
68 "home\0" Required_argument "h"
69 "gecos\0" Required_argument "g"
70 "shell\0" Required_argument "s"
71 "ingroup\0" Required_argument "G"
72 "disabled-password\0" No_argument "D"
73 "empty-password\0" No_argument "D"
74 "system\0" No_argument "S"
75 "no-create-home\0" No_argument "H"
77 #endif
80 * adduser will take a login_name as its first parameter.
81 * home, shell, gecos:
82 * can be customized via command-line parameters.
84 int adduser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
85 int adduser_main(int argc UNUSED_PARAM, char **argv)
87 struct passwd pw;
88 const char *usegroup = NULL;
89 char *p;
91 #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
92 applet_long_options = adduser_longopts;
93 #endif
95 /* got root? */
96 if (geteuid()) {
97 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
100 pw.pw_gecos = (char *)"Linux User,,,";
101 pw.pw_shell = (char *)DEFAULT_SHELL;
102 pw.pw_dir = NULL;
104 /* exactly one non-option arg */
105 opt_complementary = "=1";
106 getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
107 argv += optind;
109 /* fill in the passwd struct */
110 pw.pw_name = argv[0];
111 die_if_bad_username(pw.pw_name);
112 if (!pw.pw_dir) {
113 /* create string for $HOME if not specified already */
114 pw.pw_dir = xasprintf("/home/%s", argv[0]);
116 pw.pw_passwd = (char *)"x";
117 pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */
119 /* make sure everything is kosher and setup uid && maybe gid */
120 passwd_study(&pw);
122 p = xasprintf("x:%u:%u:%s:%s:%s", pw.pw_uid, pw.pw_gid, pw.pw_gecos, pw.pw_dir, pw.pw_shell);
123 if (update_passwd(bb_path_passwd_file, pw.pw_name, p, NULL) < 0) {
124 return EXIT_FAILURE;
126 if (ENABLE_FEATURE_CLEAN_UP)
127 free(p);
129 #if ENABLE_FEATURE_SHADOWPASSWDS
130 p = xasprintf("!:%u:0:99999:7:::", (unsigned)(time(NULL) / 86400)); /* sp->sp_lstchg */
131 /* ignore errors: if file is missing we suppose admin doesn't want it */
132 update_passwd(bb_path_shadow_file, pw.pw_name, p, NULL);
133 if (ENABLE_FEATURE_CLEAN_UP)
134 free(p);
135 #endif
137 /* add to group */
138 /* addgroup should be responsible for dealing w/ gshadow */
139 /* if using a pre-existing group, don't create one */
140 if (!usegroup)
141 addgroup_wrapper(&pw);
143 /* clear the umask for this process so it doesn't
144 * screw up the permissions on the mkdir and chown. */
145 umask(0);
146 if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
147 /* Set the owner and group so it is owned by the new user,
148 then fix up the permissions to 2755. Can't do it before
149 since chown will clear the setgid bit */
150 if (mkdir(pw.pw_dir, 0755)
151 || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid)
152 || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */
154 bb_simple_perror_msg(pw.pw_dir);
158 if (!(option_mask32 & OPT_DONT_SET_PASS)) {
159 /* interactively set passwd */
160 passwd_wrapper(pw.pw_name);
163 return 0;