int		gid;
gid_t		gid;
adduser(char *login, user_t *up){	struct group	*grp;	struct stat	st;	struct tm	tm;	time_t		expire;	char		password[PasswordLength + 1];	char		home[MaxFileNameLen];	char		buf[MaxFileNameLen];	int		sync_uid_gid;	int		masterfd;	int		ptmpfd;	int		gid;	int		cc;	int		i;	if (!valid_login(login)) {		errx(EXIT_FAILURE, "`%s' is not a valid login name", login);	}	if ((masterfd = open(_PATH_MASTERPASSWD, O_RDONLY)) < 0) {		err(EXIT_FAILURE, "can't open `%s'", _PATH_MASTERPASSWD);	}	if (flock(masterfd, LOCK_EX | LOCK_NB) < 0) {		err(EXIT_FAILURE, "can't lock `%s'", _PATH_MASTERPASSWD);	}	pw_init();	if ((ptmpfd = pw_lock(WAITSECS)) < 0) {		(void) close(masterfd);		err(EXIT_FAILURE, "can't obtain pw_lock");	}	while ((cc = read(masterfd, buf, sizeof(buf))) > 0) {		if (write(ptmpfd, buf, (size_t)(cc)) != cc) {			(void) close(masterfd);			(void) close(ptmpfd);			(void) pw_abort();			err(EXIT_FAILURE, "short write to /etc/ptmp (not %d chars)", cc);		}	}	/* if no uid was specified, get next one in [low_uid..high_uid] range */	sync_uid_gid = (strcmp(up->u_primgrp, "=uid") == 0);	if (up->u_uid == -1) {		for (i = 0 ; i < up->u_rc ; i++) {			if (getnextuid(sync_uid_gid, &up->u_uid, up->u_rv[i].r_from, up->u_rv[i].r_to)) {				break;			}		}		if (i == up->u_rc) {			(void) close(ptmpfd);			(void) pw_abort();			errx(EXIT_FAILURE, "can't get next uid for %d", up->u_uid);		}	}	/* check uid isn't already allocated */	if (!(up->u_flags & F_DUPUID) && getpwuid((uid_t)(up->u_uid)) != NULL) {		(void) close(ptmpfd);		(void) pw_abort();		errx(EXIT_FAILURE, "uid %d is already in use", up->u_uid);	}	/* if -g=uid was specified, check gid is unused */	if (sync_uid_gid) {		if (getgrgid((gid_t)(up->u_uid)) != NULL) {			(void) close(ptmpfd);			(void) pw_abort();			errx(EXIT_FAILURE, "gid %d is already in use", up->u_uid);		}		gid = up->u_uid;	} else if ((grp = getgrnam(up->u_primgrp)) != NULL) {		gid = grp->gr_gid;	} else if (is_number(up->u_primgrp) &&		   (grp = getgrgid((gid_t)atoi(up->u_primgrp))) != NULL) {		gid = grp->gr_gid;	} else {		(void) close(ptmpfd);		(void) pw_abort();		errx(EXIT_FAILURE, "group %s not found", up->u_primgrp);	}	/* check name isn't already in use */	if (!(up->u_flags & F_DUPUID) && getpwnam(login) != NULL) {		(void) close(ptmpfd);		(void) pw_abort();		errx(EXIT_FAILURE, "already a `%s' user", login);	}	if (up->u_flags & F_HOMEDIR) {		(void) strlcpy(home, up->u_home, sizeof(home));	} else {		/* if home directory hasn't been given, make it up */		(void) snprintf(home, sizeof(home), "%s/%s", up->u_basedir, login);	}	expire = 0;	if (up->u_expire != NULL) {		(void) memset(&tm, 0, sizeof(tm));		if (strptime(up->u_expire, "%c", &tm) == NULL) {			warnx("invalid time format `%s'", optarg);		} else {			expire = mktime(&tm);		}	}	if (lstat(home, &st) < 0 && !(up->u_flags & F_MKDIR)) {		warnx("Warning: home directory `%s' doesn't exist, and -m was"		    " not specified", home);	}	if (up->u_password != NULL &&	    strlen(up->u_password) <= PasswordLength) {		(void) strlcpy(password, up->u_password, sizeof(password));	} else {		(void) strlcpy(password, "*", sizeof(password));		if (up->u_password != NULL) {			warnx("Password `%s' is invalid: setting it to `%s'",				up->u_password, password);		}	}	cc = snprintf(buf, sizeof(buf), "%s:%s:%d:%d:%s:%d:%ld:%s:%s:%s\n",			login,			password,			up->u_uid,			gid,#ifdef EXTENSIONS			up->u_class,#else			"",#endif			up->u_inactive,			(long) expire,			up->u_comment,			home,			up->u_shell);	if (cc >= sizeof(buf) ||	    (strchr(up->u_comment, '&') != NULL &&	     cc + strlen(login) >= sizeof(buf))) {		(void) close(ptmpfd);		(void) pw_abort();		errx(EXIT_FAILURE, "can't add `%s', line too long", buf);	}	if (write(ptmpfd, buf, (size_t) cc) != cc) {		(void) close(ptmpfd);		(void) pw_abort();		err(EXIT_FAILURE, "can't add `%s'", buf);	}	if (up->u_flags & F_MKDIR) {		if (lstat(home, &st) == 0) {			(void) close(ptmpfd);			(void) pw_abort();			errx(EXIT_FAILURE, "home directory `%s' already exists",			    home);		} else {			if (asystem("%s -p %s", MKDIR, home) != 0) {				(void) close(ptmpfd);				(void) pw_abort();				err(EXIT_FAILURE, "can't mkdir `%s'", home);			}			(void) copydotfiles(up->u_skeldir, up->u_uid, gid, home);		}	}	if (strcmp(up->u_primgrp, "=uid") == 0 && getgrnam(login) == NULL &&	    !creategid(login, gid, login)) {		(void) close(ptmpfd);		(void) pw_abort();		err(EXIT_FAILURE, "can't create gid %d for login name %s",		    gid, login);	}	if (up->u_groupc > 0 && !append_group(login, up->u_groupc, up->u_groupv)) {		(void) close(ptmpfd);		(void) pw_abort();		errx(EXIT_FAILURE, "can't append `%s' to new groups", login);	}	(void) close(ptmpfd);	if (pw_mkdb(login, 0) < 0) {		err(EXIT_FAILURE, "pw_mkdb failed");	}	return 1;}