1 /* vi: set sw=4 ts=4: */
3 * adduser - add users to /etc/passwd and /etc/shadow
6 * Copyright (C) 1999 by Lineo, inc.
7 * Written by John Beppu <beppu@lineo.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "tinylogin.h"
33 #include <sys/param.h>
35 #include <sys/types.h>
40 # define PASSWD_FILE "passwd"
41 # define SHADOW_FILE "shadow"
44 /* structs __________________________ */
51 /* data _____________________________ */
53 /* defaults : should this be in an external file? */
54 static char *default_passwd = "x";
55 static char *default_gecos = "";
56 static char *default_home_prefix = "/home";
57 static char *default_shell = "/bin/sh";
59 #ifdef TLG_FEATURE_SHADOWPASSWDS
61 static int shadow_enabled = 0;
62 #endif /* TLG_FEATURE_SHADOWPASSWDS */
64 /* I was doing this all over the place */
65 static FILE *fopen_wrapper(const char *filename, const char *mode)
69 f = fopen(filename, mode);
71 fprintf(stderr, "adduser: %s: %s\n", filename, strerror(errno));
77 /* EDR recoded such that the uid may be passed in *p */
78 static int passwd_study(const char *filename, struct passwd *p)
84 const int max = 65000;
86 passwd = fopen_wrapper(filename, "r");
90 /* EDR if uid is out of bounds, set to min */
91 if ((p->pw_uid > max) || (p->pw_uid < min))
95 * make sure login isn't taken;
96 * find free uid and gid;
98 while ((pw = tlg_fgetpwent(passwd))) {
99 if (strcmp(pw->pw_name, p->pw_name) == 0) {
103 if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max)
104 && (pw->pw_uid >= min)) {
105 p->pw_uid = pw->pw_uid + 1;
109 /* EDR check for an already existing gid */
110 while (tlg_getgrgid(p->pw_uid) != NULL)
113 /* EDR also check for an existing group definition */
114 if (tlg_getgrnam(p->pw_name) != NULL)
117 /* EDR bounds check */
118 if ((p->pw_uid > max) || (p->pw_uid < min))
121 /* EDR create new gid always = uid */
122 p->pw_gid = p->pw_uid;
128 static void addgroup_wrapper(const char *login, gid_t gid)
131 char *argv[] = { "addgroup", "-g", NULL, NULL };
135 strncpy(group_name, login, 32);
136 argv[3] = group_name;
137 sprintf(group_id, "%d", gid);
140 addgroup_main(argc, argv);
144 static void passwd_wrapper(const char *login)
147 char *argv[] = { "passwd", NULL };
150 strncpy(login_name, login, 32);
151 argv[1] = login_name;
153 passwd_main(argc, argv);
155 #endif /* TLG_PASSWD */
157 /* putpwent(3) remix */
158 static int adduser(const char *filename, struct passwd *p)
163 #ifdef TLG_FEATURE_SHADOWPASSWDS
166 #endif /* TLG_FEATURE_SHADOWPASSWDS */
168 /* make sure everything is kosher and setup uid && gid */
169 passwd = fopen_wrapper(filename, "a");
170 if (passwd == NULL) {
174 fseek(passwd, 0, SEEK_END);
176 /* if (passwd_study(filename, p) == 0) { */
177 r = passwd_study(filename, p);
180 error_msg("%s: login already in use\n", p->pw_name);
182 error_msg("illegal uid or no uids left\n");
184 error_msg("group name %s already in use\n", p->pw_name);
186 error_msg("generic error.\n");
192 if (tlg_putpwent(p, passwd) == -1) {
198 #ifdef TLG_FEATURE_SHADOWPASSWDS
199 /* add to shadow if necessary */
200 if (shadow_enabled) {
201 shadow = fopen_wrapper(SHADOW_FILE, "a");
202 if (shadow == NULL) {
206 fseek(shadow, 0, SEEK_END);
208 sp->sp_max = 99999; /* debianish */
210 fprintf(shadow, "%s:!:%ld:%ld:%ld:%ld:::\n",
211 sp->sp_namp, sp->sp_lstchg, sp->sp_min, sp->sp_max,
215 #endif /* TLG_FEATURE_SHADOWPASSWDS */
218 /* addgroup should be responsible for dealing w/ gshadow */
219 addgroup_wrapper(p->pw_name, p->pw_gid);
221 /* Clear the umask for this process so it doesn't
222 * * screw up the permissions on the mkdir and chown. */
226 if (mkdir(p->pw_dir, 0755)) {
227 perror_msg("%s", p->pw_dir);
229 /* Set the owner and group so it is owned by the new user. */
230 if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) {
231 perror_msg("%s", p->pw_dir);
233 /* Now fix up the permissions to 2755. Can't do it before now
234 * since chown will clear the setgid bit */
235 if (chmod(p->pw_dir, 02755)) {
236 perror_msg("%s", p->pw_dir);
239 #ifndef CONFIG_DISKtel
240 /* interactively set passwd */
241 passwd_wrapper(p->pw_name);
243 #endif /* TLG_PASSWD */
249 /* return current uid (root is always uid == 0, right?) */
250 static uid_t i_am_not_root()
256 * adduser will take a login_name as its first parameter.
262 * can be customized via command-line parameters.
263 * ________________________________________________________________________ */
264 int adduser_main(int argc, char **argv)
272 char path[MAXPATHLEN];
278 usage(adduser_usage);
280 gecos = default_gecos;
281 shell = default_shell;
284 while((opt = getopt(argc, argv, "h:g:s:")) != -1){
296 usage(adduser_usage);
302 if (i_am_not_root()) {
303 error_msg_and_die( "Only root may add a user or group to the system.\n");
307 if (optind >= argc) {
308 error_msg_and_die( "adduser: no user specified\n");
310 login = argv[optind];
312 /* create string for $HOME if not specified already */
314 snprintf(path, MAXPATHLEN, "%s/%s", default_home_prefix, login);
315 path[MAXPATHLEN - 1] = 0;
318 #ifdef TLG_FEATURE_SHADOWPASSWDS
319 /* is /etc/shadow in use? */
320 /* shadow_enabled = file_exists(SHADOW_FILE); */
321 shadow_enabled = (0 == access(SHADOW_FILE, F_OK));
322 #endif /* TLG_FEATURE_SHADOWPASSWDS */
324 /* create a passwd struct */
326 pw.pw_passwd = default_passwd;
334 i = adduser(PASSWD_FILE, &pw);
339 /* $Id: adduser.c,v 1.8 2004-05-27 13:47:29 gerg Exp $ */