xref: /titanic_52/usr/src/cmd/passmgmt/passmgmt.c (revision 07925104db56e5c3eacc4865b918bd16af5cec59)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53bf5ae9eSrica  * Common Development and Distribution License (the "License").
63bf5ae9eSrica  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*07925104Sgww  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
267c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <shadow.h>
317c478bd9Sstevel@tonic-gate #include <pwd.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <time.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <locale.h>
407c478bd9Sstevel@tonic-gate #include <fcntl.h>
417c478bd9Sstevel@tonic-gate #include <secdb.h>
427c478bd9Sstevel@tonic-gate #include <user_attr.h>
43*07925104Sgww #include <nss.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	CMT_SIZE	(128+1)	/* Argument sizes + 1 (for '\0') */
467c478bd9Sstevel@tonic-gate #define	DIR_SIZE	(256+1)
477c478bd9Sstevel@tonic-gate #define	SHL_SIZE	(256+1)
487c478bd9Sstevel@tonic-gate #define	ENTRY_LENGTH	512	/* Max length of an /etc/passwd entry */
497c478bd9Sstevel@tonic-gate #define	UID_MIN		100	/* Lower bound of default UID */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #define	M_MASK		01	/* Masks for the optn_mask variable */
527c478bd9Sstevel@tonic-gate #define	L_MASK		02	/* It keeps track of which options   */
537c478bd9Sstevel@tonic-gate #define	C_MASK		04	/* have been entered */
547c478bd9Sstevel@tonic-gate #define	H_MASK		010
557c478bd9Sstevel@tonic-gate #define	U_MASK		020
567c478bd9Sstevel@tonic-gate #define	G_MASK		040
577c478bd9Sstevel@tonic-gate #define	S_MASK		0100
587c478bd9Sstevel@tonic-gate #define	O_MASK		0200
597c478bd9Sstevel@tonic-gate #define	A_MASK		0400
607c478bd9Sstevel@tonic-gate #define	D_MASK		01000
617c478bd9Sstevel@tonic-gate #define	F_MASK		02000
627c478bd9Sstevel@tonic-gate #define	E_MASK		04000
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #define	UATTR_MASK	010000
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 					/* flags for info_mask */
677c478bd9Sstevel@tonic-gate #define	LOGNAME_EXIST	01		/* logname exists */
687c478bd9Sstevel@tonic-gate #define	BOTH_FILES	02		/* touch both password files */
697c478bd9Sstevel@tonic-gate #define	WRITE_P_ENTRY	04		/* write out password entry */
707c478bd9Sstevel@tonic-gate #define	WRITE_S_ENTRY	010		/* write out shadow entry */
717c478bd9Sstevel@tonic-gate #define	NEED_DEF_UID	020		/* need default uid */
727c478bd9Sstevel@tonic-gate #define	FOUND		040		/* found the entry in password file */
737c478bd9Sstevel@tonic-gate #define	LOCKED		0100		/* did we lock the password file */
747c478bd9Sstevel@tonic-gate #define	UATTR_FILE	0200		/* touch user_attr file */
757c478bd9Sstevel@tonic-gate #define	BAD_ENT_MESSAGE	"%s: Bad entry found in /etc/passwd.  Run pwconv.\n"
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate typedef struct kvopts {
787c478bd9Sstevel@tonic-gate 	const char	option;
797c478bd9Sstevel@tonic-gate 	const char	*key;
807c478bd9Sstevel@tonic-gate 	char		*newvalue;
817c478bd9Sstevel@tonic-gate } kvopts_t;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /* mapping of extensible keywords and options */
847c478bd9Sstevel@tonic-gate kvopts_t ua_opts[] =  {
857c478bd9Sstevel@tonic-gate { 'A',	USERATTR_AUTHS_KW },
867c478bd9Sstevel@tonic-gate { 'P',	USERATTR_PROFILES_KW },
877c478bd9Sstevel@tonic-gate { 'R',	USERATTR_ROLES_KW },
887c478bd9Sstevel@tonic-gate { 'T',	USERATTR_TYPE_KW },
897c478bd9Sstevel@tonic-gate { '\0', USERATTR_DEFAULTPROJ_KW },
907c478bd9Sstevel@tonic-gate { '\0',	USERATTR_LIMPRIV_KW },
917c478bd9Sstevel@tonic-gate { '\0',	USERATTR_DFLTPRIV_KW },
927c478bd9Sstevel@tonic-gate { '\0', USERATTR_LOCK_AFTER_RETRIES_KW },
933bf5ae9eSrica { '\0', USERATTR_LABELVIEW },
943bf5ae9eSrica { '\0', USERATTR_CLEARANCE },
953bf5ae9eSrica { '\0', USERATTR_MINLABEL },
963bf5ae9eSrica { '\0', USERATTR_IDLECMD_KW },
973bf5ae9eSrica { '\0', USERATTR_IDLETIME_KW },
98*07925104Sgww { '\0', USERATTR_AUDIT_FLAGS_KW },
997c478bd9Sstevel@tonic-gate };
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #define	UA_KEYS		(sizeof (ua_opts)/sizeof (kvopts_t))
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate char defdir[] = "/home/";	/* default home directory for new user */
1057c478bd9Sstevel@tonic-gate char pwdflr[] =	"x";		/* password string for /etc/passwd */
1067c478bd9Sstevel@tonic-gate char lkstring[] = "*LK*";	/* lock string for shadow password */
1077c478bd9Sstevel@tonic-gate char nullstr[] = "";		/* null string */
1087c478bd9Sstevel@tonic-gate char	*msg;			/* pointer to error message	*/
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate #define	DATMSK "DATEMSK=/etc/datemsk"
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate #define	OUSERATTR_FILENAME	"/etc/ouser_attr"
1137c478bd9Sstevel@tonic-gate #define	USERATTR_TEMP		"/etc/uatmp"
1147c478bd9Sstevel@tonic-gate 
11549335bdeSbasabi struct uid_blk {
11649335bdeSbasabi 	struct uid_blk *link;
11749335bdeSbasabi 	uid_t low;		/* low bound for this uid block */
11849335bdeSbasabi 	uid_t high;		/* high bound for this uid block */
11949335bdeSbasabi };
12049335bdeSbasabi 
1217c478bd9Sstevel@tonic-gate extern userattr_t *fgetuserattr(FILE *);
1227c478bd9Sstevel@tonic-gate 
12349335bdeSbasabi 
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate  * Declare all functions that do not return integers.  This is here
1267c478bd9Sstevel@tonic-gate  * to get rid of some lint messages
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate 
12949335bdeSbasabi void	uid_bcom(struct uid_blk *), add_ublk(uid_t, struct uid_blk *),
13049335bdeSbasabi 	bad_perm(void),
13149335bdeSbasabi 	bad_usage(char *), bad_arg(char *), bad_uid(void), bad_pasf(void),
13249335bdeSbasabi 	file_error(void), bad_news(void), no_lock(void), add_uid(uid_t),
13349335bdeSbasabi 	rid_tmpf(void), ck_p_sz(struct passwd *), ck_s_sz(struct spwd *),
13449335bdeSbasabi 	bad_name(char *), bad_uattr(void);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate void file_copy(FILE *spf, long NIS_pos);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate static FILE *fp_ptemp, *fp_stemp, *fp_uatemp;
1397c478bd9Sstevel@tonic-gate static int fd_ptemp, fd_stemp, fd_uatemp;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * The uid_blk structure is used in the search for the default
1437c478bd9Sstevel@tonic-gate  * uid.  Each uid_blk represent a range of uid(s) that are currently
1447c478bd9Sstevel@tonic-gate  * used on the system.
1457c478bd9Sstevel@tonic-gate  */
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate #ifndef att
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * getspnan routine that ONLY looks at the local shadow file
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate struct spwd *
15349335bdeSbasabi local_getspnam(char *name)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	FILE *shadf;
1567c478bd9Sstevel@tonic-gate 	struct spwd *sp;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	if ((shadf = fopen("/etc/shadow", "r")) == NULL)
1597c478bd9Sstevel@tonic-gate 		return (NULL);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	while ((sp = fgetspent(shadf)) != NULL) {
1627c478bd9Sstevel@tonic-gate 		if (strcmp(sp->sp_namp, name) == 0)
1637c478bd9Sstevel@tonic-gate 			break;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	fclose(shadf);
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	return (sp);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate #endif
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate static void
1737c478bd9Sstevel@tonic-gate putuserattrent(userattr_t *user, FILE *f)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	int		i, j;
1767c478bd9Sstevel@tonic-gate 	char		*key;
1777c478bd9Sstevel@tonic-gate 	char		*val;
1787c478bd9Sstevel@tonic-gate 	kv_t		*kv_pair;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	/*
1817c478bd9Sstevel@tonic-gate 	 * Avoid trivial entries.  Those with no attributes or with
1827c478bd9Sstevel@tonic-gate 	 * only "type=normal".  This retains backward compatibility.
1837c478bd9Sstevel@tonic-gate 	 */
1847c478bd9Sstevel@tonic-gate 	if (user->attr == NULL)
1857c478bd9Sstevel@tonic-gate 		return;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	kv_pair = user->attr->data;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	for (i = j = 0; i < user->attr->length; i++) {
1907c478bd9Sstevel@tonic-gate 		key = kv_pair[i].key;
1917c478bd9Sstevel@tonic-gate 		val = kv_pair[i].value;
1927c478bd9Sstevel@tonic-gate 		if ((key == NULL) || (val == NULL))
1937c478bd9Sstevel@tonic-gate 			break;
1947c478bd9Sstevel@tonic-gate 		if (strlen(val) == 0 ||
1957c478bd9Sstevel@tonic-gate 		    (strcmp(key, USERATTR_TYPE_KW) == 0 &&
1967c478bd9Sstevel@tonic-gate 		    strcmp(val, USERATTR_TYPE_NORMAL_KW) == 0))
1977c478bd9Sstevel@tonic-gate 			continue;
1987c478bd9Sstevel@tonic-gate 		j++;
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 	if (j == 0)
2017c478bd9Sstevel@tonic-gate 		return;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	(void) fprintf(f, "%s:%s:%s:%s:", user->name, user->qualifier,
2047c478bd9Sstevel@tonic-gate 	    user->res1, user->res2);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	for (i = j = 0; i < user->attr->length; i++) {
2077c478bd9Sstevel@tonic-gate 		key = kv_pair[i].key;
208*07925104Sgww 		val = _escape(kv_pair[i].value, KV_SPECIAL);
2097c478bd9Sstevel@tonic-gate 		if ((key == NULL) || (val == NULL))
2107c478bd9Sstevel@tonic-gate 			break;
2117c478bd9Sstevel@tonic-gate 		if (strlen(val) == 0)
2127c478bd9Sstevel@tonic-gate 			continue;
2137c478bd9Sstevel@tonic-gate 		if (j > 0)
2147c478bd9Sstevel@tonic-gate 			(void) fprintf(f, KV_DELIMITER);
2157c478bd9Sstevel@tonic-gate 		(void) fprintf(f, "%s=%s", key, val);
2167c478bd9Sstevel@tonic-gate 		j++;
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	(void) fprintf(f, "\n");
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate static void
2227c478bd9Sstevel@tonic-gate assign_attr(userattr_t *user, const char *newkey, char *val) {
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	int		i;
2257c478bd9Sstevel@tonic-gate 	char		*key;
2267c478bd9Sstevel@tonic-gate 	kv_t		*kv_pair;
2277c478bd9Sstevel@tonic-gate 	int		avail = -1;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	if (user->attr != NULL) {
2307c478bd9Sstevel@tonic-gate 		kv_pair = user->attr->data;
2317c478bd9Sstevel@tonic-gate 		for (i = 0; i < user->attr->length; i++) {
2327c478bd9Sstevel@tonic-gate 			key = kv_pair[i].key;
2337c478bd9Sstevel@tonic-gate 			if (key == NULL) {
2347c478bd9Sstevel@tonic-gate 				avail = i;
2357c478bd9Sstevel@tonic-gate 				continue;
2367c478bd9Sstevel@tonic-gate 			} else if (strcmp(key, newkey) == 0) {
2377c478bd9Sstevel@tonic-gate 				kv_pair[i].value = strdup(val);
2387c478bd9Sstevel@tonic-gate 				return;
2397c478bd9Sstevel@tonic-gate 			}
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		if (avail == -1)
2437c478bd9Sstevel@tonic-gate 			avail = user->attr->length++;
2447c478bd9Sstevel@tonic-gate 		kv_pair[avail].key = strdup(newkey);
2457c478bd9Sstevel@tonic-gate 		kv_pair[avail].value = strdup(val);
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate static void
2507c478bd9Sstevel@tonic-gate unassign_role(userattr_t *user, char *rolelist, char *role) {
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	char *roleptr;
2537c478bd9Sstevel@tonic-gate 	char *templist;
2547c478bd9Sstevel@tonic-gate 	char *temprole;
2557c478bd9Sstevel@tonic-gate 	int  length;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	roleptr = rolelist;
2587c478bd9Sstevel@tonic-gate 	templist = strdup(roleptr);
2597c478bd9Sstevel@tonic-gate 	temprole = strtok(templist, ",");
2607c478bd9Sstevel@tonic-gate 	while (temprole) {
2617c478bd9Sstevel@tonic-gate 		if (strcmp(temprole, role) == 0) {
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 			length = strlen(role);
2647c478bd9Sstevel@tonic-gate 			roleptr += temprole - templist;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 			if (*(roleptr + length) == ',')
2677c478bd9Sstevel@tonic-gate 				length++;
2687c478bd9Sstevel@tonic-gate 			strcpy(roleptr, roleptr + length);
2697c478bd9Sstevel@tonic-gate 			length = strlen(roleptr) - 1;
2707c478bd9Sstevel@tonic-gate 			if (*(roleptr + length) == ',')
2717c478bd9Sstevel@tonic-gate 				*(roleptr + length) = '\0';
2727c478bd9Sstevel@tonic-gate 			assign_attr(user, USERATTR_ROLES_KW, rolelist);
2737c478bd9Sstevel@tonic-gate 			break;
2747c478bd9Sstevel@tonic-gate 		} else {
2757c478bd9Sstevel@tonic-gate 			temprole = strtok(NULL, ",");
2767c478bd9Sstevel@tonic-gate 		}
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate struct uid_blk *uid_sp;
2817c478bd9Sstevel@tonic-gate char *prognamp;			/* program name */
2827c478bd9Sstevel@tonic-gate extern int errno;
2837c478bd9Sstevel@tonic-gate int optn_mask = 0, info_mask = 0;
2847c478bd9Sstevel@tonic-gate extern int getdate_err;
2857c478bd9Sstevel@tonic-gate 
28649335bdeSbasabi int
28749335bdeSbasabi main(int argc, char **argv)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	int c, i;
2907c478bd9Sstevel@tonic-gate 	char *lognamp, *char_p;
2917c478bd9Sstevel@tonic-gate 	int end_of_file = 0;
2927c478bd9Sstevel@tonic-gate 	int error;
2937c478bd9Sstevel@tonic-gate 	long date = 0;
2947c478bd9Sstevel@tonic-gate 	FILE *pwf, *spf, *uaf;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	struct passwd *pw_ptr1p, passwd_st;
2977c478bd9Sstevel@tonic-gate 	struct spwd *sp_ptr1p, shadow_st;
2987c478bd9Sstevel@tonic-gate 	userattr_t *ua_ptr1p, userattr_st;
2997c478bd9Sstevel@tonic-gate 	static kv_t ua_kv[KV_ADD_KEYS];
3007c478bd9Sstevel@tonic-gate 	kva_t ua_kva;
3017c478bd9Sstevel@tonic-gate 	struct stat statbuf;
3027c478bd9Sstevel@tonic-gate 	struct tm *tm_ptr;
3037c478bd9Sstevel@tonic-gate 	int NIS_entry_seen;		/* NIS scanning flag */
3047c478bd9Sstevel@tonic-gate 	/*
3057c478bd9Sstevel@tonic-gate 	 * NIS start pos, really pointer to first entry AFTER first
3067c478bd9Sstevel@tonic-gate 	 * NIS-referant entry
3077c478bd9Sstevel@tonic-gate 	 */
3087c478bd9Sstevel@tonic-gate 	long NIS_pos;
3097c478bd9Sstevel@tonic-gate 	long cur_pos;		/* Current pos, used with nis-pos above */
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
3147c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
3157c478bd9Sstevel@tonic-gate #endif
3167c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	tzset();
3197c478bd9Sstevel@tonic-gate 	/* Get program name */
3207c478bd9Sstevel@tonic-gate 	prognamp = argv[0];
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/* Check identity */
3237c478bd9Sstevel@tonic-gate 	if (geteuid() != 0)
3247c478bd9Sstevel@tonic-gate 		bad_perm();
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/* Lock the password file(s) */
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	if (lckpwdf() != 0)
3297c478bd9Sstevel@tonic-gate 		no_lock();
3307c478bd9Sstevel@tonic-gate 	info_mask |= LOCKED;		/* remember we locked */
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	/* initialize the two structures */
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	passwd_st.pw_passwd = pwdflr;		/* bogus password */
3357c478bd9Sstevel@tonic-gate 	passwd_st.pw_name = nullstr;		/* login name */
3367c478bd9Sstevel@tonic-gate 	passwd_st.pw_uid = -1;			/* no uid */
3377c478bd9Sstevel@tonic-gate 	passwd_st.pw_gid = 1;			/* default gid */
3387c478bd9Sstevel@tonic-gate 	passwd_st.pw_age = nullstr;		/* no aging info. */
3397c478bd9Sstevel@tonic-gate 	passwd_st.pw_comment = nullstr;	/* no comments */
3407c478bd9Sstevel@tonic-gate 	passwd_st.pw_gecos = nullstr;		/* no comments */
3417c478bd9Sstevel@tonic-gate 	passwd_st.pw_dir = nullstr;		/* no default directory */
3427c478bd9Sstevel@tonic-gate 	passwd_st.pw_shell = nullstr;		/* no default shell */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	shadow_st.sp_namp = nullstr;	/* no name */
3457c478bd9Sstevel@tonic-gate 	shadow_st.sp_pwdp = lkstring;	/* locked password */
3467c478bd9Sstevel@tonic-gate 	shadow_st.sp_lstchg = -1;	/* no lastchanged date */
3477c478bd9Sstevel@tonic-gate 	shadow_st.sp_min = -1;	/* no min */
3487c478bd9Sstevel@tonic-gate 	shadow_st.sp_max = -1;	/* no max */
3497c478bd9Sstevel@tonic-gate 	shadow_st.sp_warn = -1; 	/* no warn */
3507c478bd9Sstevel@tonic-gate 	shadow_st.sp_inact = -1;	/* no inactive */
3517c478bd9Sstevel@tonic-gate 	shadow_st.sp_expire = -1;	/* no expire */
3527c478bd9Sstevel@tonic-gate 	shadow_st.sp_flag = 0;	/* no flag */
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	userattr_st.name = nullstr;
3557c478bd9Sstevel@tonic-gate 	userattr_st.qualifier = nullstr;
3567c478bd9Sstevel@tonic-gate 	userattr_st.res1 = nullstr;
3577c478bd9Sstevel@tonic-gate 	userattr_st.res2 = nullstr;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	ua_kva.length = 1;
3607c478bd9Sstevel@tonic-gate 	ua_kv[0].key = USERATTR_TYPE_KW;
3617c478bd9Sstevel@tonic-gate 	ua_kv[0].value = USERATTR_TYPE_NORMAL_KW;
3627c478bd9Sstevel@tonic-gate 	ua_kva.data = ua_kv;
3637c478bd9Sstevel@tonic-gate 	userattr_st.attr = &ua_kva;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	/* parse the command line */
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv,
3687c478bd9Sstevel@tonic-gate 	    "ml:c:h:u:g:s:f:e:k:A:P:R:T:oadK:")) != -1) {
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		switch (c) {
3717c478bd9Sstevel@tonic-gate 		case 'm':
3727c478bd9Sstevel@tonic-gate 			/* Modify */
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 			if ((A_MASK|D_MASK|M_MASK) & optn_mask)
3757c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 			optn_mask |= M_MASK;
3787c478bd9Sstevel@tonic-gate 			break;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 		case 'l' :
3817c478bd9Sstevel@tonic-gate 			/* Change logname */
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 			if ((A_MASK|D_MASK|L_MASK) & optn_mask)
3847c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 			if (strpbrk(optarg, ":\n") ||
3877c478bd9Sstevel@tonic-gate 			    strlen(optarg) == 0)
3887c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -l");
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 			optn_mask |= L_MASK;
3917c478bd9Sstevel@tonic-gate 			passwd_st.pw_name = optarg;
3927c478bd9Sstevel@tonic-gate 			shadow_st.sp_namp = optarg;
3937c478bd9Sstevel@tonic-gate 			userattr_st.name = optarg;
3947c478bd9Sstevel@tonic-gate 			break;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 		case 'f' :
3977c478bd9Sstevel@tonic-gate 			/* set inactive */
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 			if ((D_MASK|F_MASK) & optn_mask)
4007c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
4017c478bd9Sstevel@tonic-gate 			if (((shadow_st.sp_inact =
4027c478bd9Sstevel@tonic-gate 			    strtol(optarg, &char_p, 10)) < (long)0) ||
4037c478bd9Sstevel@tonic-gate 			    (*char_p != '\0') ||
4047c478bd9Sstevel@tonic-gate 			    strlen(optarg) == 0)
4057c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -f");
4067c478bd9Sstevel@tonic-gate 			if (shadow_st.sp_inact == 0)
4077c478bd9Sstevel@tonic-gate 				shadow_st.sp_inact = -1;
4087c478bd9Sstevel@tonic-gate 			optn_mask |= F_MASK;
4097c478bd9Sstevel@tonic-gate 			break;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 		case 'e' :
4127c478bd9Sstevel@tonic-gate 			/* set expire date */
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 			if ((D_MASK|E_MASK) & optn_mask)
4157c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 			if ((strlen(optarg)) < (size_t)2)
4187c478bd9Sstevel@tonic-gate 				shadow_st.sp_expire = -1;
4197c478bd9Sstevel@tonic-gate 			else {
4207c478bd9Sstevel@tonic-gate 				putenv(DATMSK);
4217c478bd9Sstevel@tonic-gate 				if ((tm_ptr =  getdate(optarg)) == NULL) {
4227c478bd9Sstevel@tonic-gate 					msg = "Invalid argument to option -e";
4237c478bd9Sstevel@tonic-gate 					bad_arg(msg);
4247c478bd9Sstevel@tonic-gate 				}
4257c478bd9Sstevel@tonic-gate 				if ((date =  mktime(tm_ptr)) < 0) {
4267c478bd9Sstevel@tonic-gate 					msg = "Invalid argument to option -e";
4277c478bd9Sstevel@tonic-gate 					bad_arg(msg);
4287c478bd9Sstevel@tonic-gate 				}
4297c478bd9Sstevel@tonic-gate 				shadow_st.sp_expire = (date / DAY);
4307c478bd9Sstevel@tonic-gate 				if (shadow_st.sp_expire <= DAY_NOW) {
4317c478bd9Sstevel@tonic-gate 					msg = "Invalid argument to option -e";
4327c478bd9Sstevel@tonic-gate 					bad_arg(msg);
4337c478bd9Sstevel@tonic-gate 				}
4347c478bd9Sstevel@tonic-gate 			}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 			optn_mask |= E_MASK;
4377c478bd9Sstevel@tonic-gate 			break;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 		case 'c' :
4407c478bd9Sstevel@tonic-gate 			/* The comment */
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 			if ((D_MASK|C_MASK) & optn_mask)
4437c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 			if (strlen(optarg) > (size_t)CMT_SIZE ||
4467c478bd9Sstevel@tonic-gate 			    strpbrk(optarg, ":\n"))
4477c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -c");
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 				optn_mask |= C_MASK;
4507c478bd9Sstevel@tonic-gate 				passwd_st.pw_comment = optarg;
4517c478bd9Sstevel@tonic-gate 				passwd_st.pw_gecos = optarg;
4527c478bd9Sstevel@tonic-gate 				break;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 		case 'h' :
4557c478bd9Sstevel@tonic-gate 			/* The home directory */
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 			if ((D_MASK|H_MASK) & optn_mask)
4587c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 			if (strlen(optarg) > (size_t)DIR_SIZE ||
4617c478bd9Sstevel@tonic-gate 			    strpbrk(optarg, ":\n"))
4627c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -h");
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 			optn_mask |= H_MASK;
4657c478bd9Sstevel@tonic-gate 			passwd_st.pw_dir = optarg;
4667c478bd9Sstevel@tonic-gate 			break;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		case 'u' :
4697c478bd9Sstevel@tonic-gate 			/* The uid */
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 			if ((D_MASK|U_MASK) & optn_mask)
4727c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 			optn_mask |= U_MASK;
4757c478bd9Sstevel@tonic-gate 			passwd_st.pw_uid = (uid_t)strtol(optarg, &char_p, 10);
4767c478bd9Sstevel@tonic-gate 			if ((*char_p != '\0') ||
4777c478bd9Sstevel@tonic-gate 			    (passwd_st.pw_uid < 0) ||
4787c478bd9Sstevel@tonic-gate 			    (strlen(optarg) == 0))
4797c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -u");
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 			break;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 		case 'g' :
4847c478bd9Sstevel@tonic-gate 			/* The gid */
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			if ((D_MASK|G_MASK) & optn_mask)
4877c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 			optn_mask |= G_MASK;
4907c478bd9Sstevel@tonic-gate 			passwd_st.pw_gid = (gid_t)strtol(optarg, &char_p, 10);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 			if ((*char_p != '\0') || (passwd_st.pw_gid < 0) ||
4937c478bd9Sstevel@tonic-gate 			    (strlen(optarg) == 0))
4947c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -g");
4957c478bd9Sstevel@tonic-gate 			break;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 		case 's' :
4987c478bd9Sstevel@tonic-gate 			/* The shell */
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 			if ((D_MASK|S_MASK) & optn_mask)
5017c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 			if (strlen(optarg) > (size_t)SHL_SIZE ||
5047c478bd9Sstevel@tonic-gate 			    strpbrk(optarg, ":\n"))
5057c478bd9Sstevel@tonic-gate 				bad_arg("Invalid argument to option -s");
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 			optn_mask |= S_MASK;
5087c478bd9Sstevel@tonic-gate 			passwd_st.pw_shell = optarg;
5097c478bd9Sstevel@tonic-gate 			break;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 		case 'o' :
5127c478bd9Sstevel@tonic-gate 			/* Override unique uid	*/
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 			if ((D_MASK|O_MASK) & optn_mask)
5157c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 			optn_mask |= O_MASK;
5187c478bd9Sstevel@tonic-gate 			break;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		case 'a' :
5217c478bd9Sstevel@tonic-gate 			/* Add */
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 			if ((A_MASK|M_MASK|D_MASK|L_MASK) & optn_mask)
5247c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 			optn_mask |= A_MASK;
5277c478bd9Sstevel@tonic-gate 			break;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 		case 'd' :
5307c478bd9Sstevel@tonic-gate 			/* Delete */
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 			if ((D_MASK|M_MASK|L_MASK|C_MASK|
5337c478bd9Sstevel@tonic-gate 			    H_MASK|U_MASK|G_MASK|S_MASK|
5347c478bd9Sstevel@tonic-gate 			    O_MASK|A_MASK) & optn_mask)
5357c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 			optn_mask |= D_MASK;
5387c478bd9Sstevel@tonic-gate 			break;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 		case 'K':
5417c478bd9Sstevel@tonic-gate 			if (D_MASK & optn_mask)
5427c478bd9Sstevel@tonic-gate 				bad_usage("Invalid combination of options");
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 			char_p = strchr(optarg, '=');
5457c478bd9Sstevel@tonic-gate 			if (char_p == NULL)
5467c478bd9Sstevel@tonic-gate 				bad_usage("Missing value in -K option");
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 			*char_p++ = '\0';
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 			for (i = 0; i < UA_KEYS; i++) {
5517c478bd9Sstevel@tonic-gate 				if (strcmp(optarg, ua_opts[i].key) == 0) {
552*07925104Sgww 					ua_opts[i].newvalue =
553*07925104Sgww 					    _escape(char_p, KV_SPECIAL);
5547c478bd9Sstevel@tonic-gate 					assign_attr(&userattr_st, optarg,
5557c478bd9Sstevel@tonic-gate 					    char_p);
5567c478bd9Sstevel@tonic-gate 					break;
5577c478bd9Sstevel@tonic-gate 				}
5587c478bd9Sstevel@tonic-gate 			}
5597c478bd9Sstevel@tonic-gate 			if (i == UA_KEYS)
5607c478bd9Sstevel@tonic-gate 				bad_usage("bad key");
5617c478bd9Sstevel@tonic-gate 			optn_mask |= UATTR_MASK;
5627c478bd9Sstevel@tonic-gate 			break;
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 		case '?' :
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 			bad_usage("");
5677c478bd9Sstevel@tonic-gate 			break;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 		default :
5707c478bd9Sstevel@tonic-gate 			/* Extended User Attributes */
5717c478bd9Sstevel@tonic-gate 			{
5727c478bd9Sstevel@tonic-gate 				int j;
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 				for (j = 0; j < UA_KEYS; j++) {
5757c478bd9Sstevel@tonic-gate 					if (ua_opts[j].option == (char)c) {
5767c478bd9Sstevel@tonic-gate 						if ((D_MASK) & optn_mask)
577*07925104Sgww 							bad_usage("Invalid "
578*07925104Sgww 							"combination of "
579*07925104Sgww 							" options");
5807c478bd9Sstevel@tonic-gate 						optn_mask |= UATTR_MASK;
5817c478bd9Sstevel@tonic-gate 						assign_attr(&userattr_st,
582*07925104Sgww 						    ua_opts[j].key,
583*07925104Sgww 						    _escape(optarg,
584*07925104Sgww 						    KV_SPECIAL));
585*07925104Sgww 						ua_opts[j].newvalue =
586*07925104Sgww 						    _escape(optarg, KV_SPECIAL);
5877c478bd9Sstevel@tonic-gate 						break;
5887c478bd9Sstevel@tonic-gate 					}
5897c478bd9Sstevel@tonic-gate 				}
5907c478bd9Sstevel@tonic-gate 				break;
5917c478bd9Sstevel@tonic-gate 			}
5927c478bd9Sstevel@tonic-gate 		}
5937c478bd9Sstevel@tonic-gate 	}
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	/* check command syntax for the following errors */
5967c478bd9Sstevel@tonic-gate 	/* too few or too many arguments */
5977c478bd9Sstevel@tonic-gate 	/* no -a -m or -d option */
5987c478bd9Sstevel@tonic-gate 	/* -o without -u */
5997c478bd9Sstevel@tonic-gate 	/* -m with no other option */
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	if (optind == argc || argc > (optind+1) ||
6027c478bd9Sstevel@tonic-gate 	    !((A_MASK|M_MASK|D_MASK) & optn_mask) ||
6037c478bd9Sstevel@tonic-gate 	    ((optn_mask & O_MASK) && !(optn_mask & U_MASK)) ||
6047c478bd9Sstevel@tonic-gate 	    ((optn_mask & M_MASK) &&
6057c478bd9Sstevel@tonic-gate 	    !(optn_mask &
6067c478bd9Sstevel@tonic-gate 	    (L_MASK|C_MASK|H_MASK|U_MASK|G_MASK|S_MASK|F_MASK|
6077c478bd9Sstevel@tonic-gate 	    E_MASK|UATTR_MASK))))
6087c478bd9Sstevel@tonic-gate 		bad_usage("Invalid command syntax");
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/* null string argument or bad characters ? */
6117c478bd9Sstevel@tonic-gate 	if ((strlen(argv[optind]) == 0) || strpbrk(argv[optind], ":\n"))
6127c478bd9Sstevel@tonic-gate 		bad_arg("Invalid name");
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	lognamp = argv [optind];
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	/*
6177c478bd9Sstevel@tonic-gate 	 * if we are adding a new user or modifying an existing user
6187c478bd9Sstevel@tonic-gate 	 * (not the logname), then copy logname into the two data
6197c478bd9Sstevel@tonic-gate 	 *  structures
6207c478bd9Sstevel@tonic-gate 	 */
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	if ((A_MASK & optn_mask) ||
6237c478bd9Sstevel@tonic-gate 	    ((M_MASK & optn_mask) && !(optn_mask & L_MASK))) {
6247c478bd9Sstevel@tonic-gate 		passwd_st.pw_name = argv [optind];
6257c478bd9Sstevel@tonic-gate 		shadow_st.sp_namp = argv [optind];
6267c478bd9Sstevel@tonic-gate 		userattr_st.name = argv [optind];
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	/* Put in directory if we are adding and we need a default */
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	if (!(optn_mask & H_MASK) && (optn_mask & A_MASK)) {
6327c478bd9Sstevel@tonic-gate 		if ((passwd_st.pw_dir = malloc((size_t)DIR_SIZE)) == NULL)
6337c478bd9Sstevel@tonic-gate 			file_error();
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 		*passwd_st.pw_dir = '\0';
6367c478bd9Sstevel@tonic-gate 		(void) strcat(passwd_st.pw_dir, defdir);
6377c478bd9Sstevel@tonic-gate 		(void) strcat(passwd_st.pw_dir, lognamp);
6387c478bd9Sstevel@tonic-gate 	}
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 	/* Check the number of password files we are touching */
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	if ((!((M_MASK & optn_mask) && !(L_MASK & optn_mask))) ||
6437c478bd9Sstevel@tonic-gate 	    ((M_MASK & optn_mask) && ((E_MASK & optn_mask) ||
6447c478bd9Sstevel@tonic-gate 	    (F_MASK & optn_mask))))
6457c478bd9Sstevel@tonic-gate 		info_mask |= BOTH_FILES;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	if ((D_MASK|L_MASK|UATTR_MASK) & optn_mask)
6487c478bd9Sstevel@tonic-gate 		info_mask |= UATTR_FILE;
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	/* Open the temporary file(s) with appropriate permission mask */
6517c478bd9Sstevel@tonic-gate 	/* and the appropriate owner */
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	if (stat(PASSWD, &statbuf) < 0)
6547c478bd9Sstevel@tonic-gate 		file_error();
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
6577c478bd9Sstevel@tonic-gate 	if (fd_ptemp == -1) {
6587c478bd9Sstevel@tonic-gate 		if (errno == EEXIST) {
6597c478bd9Sstevel@tonic-gate 			if (unlink(PASSTEMP)) {
6607c478bd9Sstevel@tonic-gate 				msg = "%s: warning: cannot unlink %s\n";
6617c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(msg), prognamp,
6627c478bd9Sstevel@tonic-gate 				    PASSTEMP);
6637c478bd9Sstevel@tonic-gate 			}
6647c478bd9Sstevel@tonic-gate 			fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY,
6657c478bd9Sstevel@tonic-gate 			    statbuf.st_mode);
6667c478bd9Sstevel@tonic-gate 			if (fd_ptemp == -1) {
6677c478bd9Sstevel@tonic-gate 				file_error();
6687c478bd9Sstevel@tonic-gate 			}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 		} else
6717c478bd9Sstevel@tonic-gate 			file_error();
6727c478bd9Sstevel@tonic-gate 	}
6737c478bd9Sstevel@tonic-gate 	fp_ptemp = fdopen(fd_ptemp, "w");
6747c478bd9Sstevel@tonic-gate 	if (fp_ptemp == NULL)
6757c478bd9Sstevel@tonic-gate 		file_error();
6767c478bd9Sstevel@tonic-gate 	error = fchown(fd_ptemp, statbuf.st_uid, statbuf.st_gid);
6777c478bd9Sstevel@tonic-gate 	if (error == 0)
6787c478bd9Sstevel@tonic-gate 		error = fchmod(fd_ptemp, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
6797c478bd9Sstevel@tonic-gate 	if (error != 0) {
6807c478bd9Sstevel@tonic-gate 		(void) fclose(fp_ptemp);
6817c478bd9Sstevel@tonic-gate 		if (unlink(PASSTEMP)) {
6827c478bd9Sstevel@tonic-gate 			msg = "%s: warning: cannot unlink %s\n";
6837c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(msg), prognamp,
6847c478bd9Sstevel@tonic-gate 			    PASSTEMP);
6857c478bd9Sstevel@tonic-gate 		}
6867c478bd9Sstevel@tonic-gate 		file_error();
6877c478bd9Sstevel@tonic-gate 	}
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	if (info_mask & BOTH_FILES) {
6907c478bd9Sstevel@tonic-gate 		if (stat(SHADOW, &statbuf) < 0) {
6917c478bd9Sstevel@tonic-gate 			rid_tmpf();
6927c478bd9Sstevel@tonic-gate 			file_error();
6937c478bd9Sstevel@tonic-gate 		}
6947c478bd9Sstevel@tonic-gate 		fd_stemp = open(SHADTEMP, O_CREAT|O_EXCL|O_WRONLY,
6957c478bd9Sstevel@tonic-gate 		    statbuf.st_mode);
6967c478bd9Sstevel@tonic-gate 		if (fd_stemp == -1) {
6977c478bd9Sstevel@tonic-gate 			if (errno == EEXIST) {
6987c478bd9Sstevel@tonic-gate 				if (unlink(SHADTEMP)) {
6997c478bd9Sstevel@tonic-gate 					msg = "%s: warning: cannot unlink %s\n";
7007c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(msg),
7017c478bd9Sstevel@tonic-gate 					    prognamp, SHADTEMP);
7027c478bd9Sstevel@tonic-gate 				}
7037c478bd9Sstevel@tonic-gate 				fd_stemp = open(SHADTEMP,
704*07925104Sgww 				    O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
7057c478bd9Sstevel@tonic-gate 				if (fd_stemp == -1) {
7067c478bd9Sstevel@tonic-gate 					rid_tmpf();
7077c478bd9Sstevel@tonic-gate 					file_error();
7087c478bd9Sstevel@tonic-gate 				}
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 			} else {
7117c478bd9Sstevel@tonic-gate 				rid_tmpf();
7127c478bd9Sstevel@tonic-gate 				file_error();
7137c478bd9Sstevel@tonic-gate 			}
7147c478bd9Sstevel@tonic-gate 		}
7157c478bd9Sstevel@tonic-gate 		fp_stemp = fdopen(fd_stemp, "w");
7167c478bd9Sstevel@tonic-gate 		if (fp_stemp == NULL) {
7177c478bd9Sstevel@tonic-gate 			rid_tmpf();
7187c478bd9Sstevel@tonic-gate 			file_error();
7197c478bd9Sstevel@tonic-gate 		}
7207c478bd9Sstevel@tonic-gate 		error = fchown(fd_stemp, statbuf.st_uid, statbuf.st_gid);
7217c478bd9Sstevel@tonic-gate 		if (error == 0)
7227c478bd9Sstevel@tonic-gate 			error = fchmod(fd_stemp, S_IRUSR);
7237c478bd9Sstevel@tonic-gate 		if (error != 0) {
7247c478bd9Sstevel@tonic-gate 			rid_tmpf();
7257c478bd9Sstevel@tonic-gate 			file_error();
7267c478bd9Sstevel@tonic-gate 		}
7277c478bd9Sstevel@tonic-gate 	}
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	if (info_mask & UATTR_FILE) {
7307c478bd9Sstevel@tonic-gate 		if (stat(USERATTR_FILENAME, &statbuf) < 0) {
7317c478bd9Sstevel@tonic-gate 			rid_tmpf();
7327c478bd9Sstevel@tonic-gate 			file_error();
7337c478bd9Sstevel@tonic-gate 		}
7347c478bd9Sstevel@tonic-gate 		fd_uatemp = open(USERATTR_TEMP, O_CREAT|O_EXCL|O_WRONLY,
7357c478bd9Sstevel@tonic-gate 		    statbuf.st_mode);
7367c478bd9Sstevel@tonic-gate 		if (fd_uatemp == -1) {
7377c478bd9Sstevel@tonic-gate 			if (errno == EEXIST) {
7387c478bd9Sstevel@tonic-gate 				if (unlink(USERATTR_TEMP)) {
7397c478bd9Sstevel@tonic-gate 					msg = "%s: warning: cannot unlink %s\n";
7407c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(msg),
7417c478bd9Sstevel@tonic-gate 					    prognamp, USERATTR_TEMP);
7427c478bd9Sstevel@tonic-gate 				}
7437c478bd9Sstevel@tonic-gate 				fd_uatemp = open(USERATTR_TEMP,
744*07925104Sgww 				    O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
7457c478bd9Sstevel@tonic-gate 				if (fd_uatemp == -1) {
7467c478bd9Sstevel@tonic-gate 					rid_tmpf();
7477c478bd9Sstevel@tonic-gate 					file_error();
7487c478bd9Sstevel@tonic-gate 				}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 			} else {
7517c478bd9Sstevel@tonic-gate 				rid_tmpf();
7527c478bd9Sstevel@tonic-gate 				file_error();
7537c478bd9Sstevel@tonic-gate 			}
7547c478bd9Sstevel@tonic-gate 		}
7557c478bd9Sstevel@tonic-gate 		fp_uatemp = fdopen(fd_uatemp, "w");
7567c478bd9Sstevel@tonic-gate 		if (fp_uatemp == NULL) {
7577c478bd9Sstevel@tonic-gate 			rid_tmpf();
7587c478bd9Sstevel@tonic-gate 			file_error();
7597c478bd9Sstevel@tonic-gate 		}
7607c478bd9Sstevel@tonic-gate 		error = fchown(fd_uatemp, statbuf.st_uid, statbuf.st_gid);
7617c478bd9Sstevel@tonic-gate 		if (error == 0)
7627c478bd9Sstevel@tonic-gate 			error = fchmod(fd_uatemp,
7637c478bd9Sstevel@tonic-gate 			    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
7647c478bd9Sstevel@tonic-gate 		if (error != 0) {
7657c478bd9Sstevel@tonic-gate 			rid_tmpf();
7667c478bd9Sstevel@tonic-gate 			file_error();
7677c478bd9Sstevel@tonic-gate 		}
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 	/* Default uid needed ? */
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	if (!(optn_mask & U_MASK) && (optn_mask & A_MASK)) {
7727c478bd9Sstevel@tonic-gate 		/* mark it in the information mask */
7737c478bd9Sstevel@tonic-gate 		info_mask |= NEED_DEF_UID;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 		/* create the head of the uid number list */
7767c478bd9Sstevel@tonic-gate 		uid_sp = malloc(sizeof (struct uid_blk));
7777c478bd9Sstevel@tonic-gate 		if (uid_sp == NULL) {
7787c478bd9Sstevel@tonic-gate 			rid_tmpf();
7797c478bd9Sstevel@tonic-gate 			file_error();
7807c478bd9Sstevel@tonic-gate 		}
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 		uid_sp->link = NULL;
7837c478bd9Sstevel@tonic-gate 		uid_sp->low = (UID_MIN -1);
7847c478bd9Sstevel@tonic-gate 		uid_sp->high = (UID_MIN -1);
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	/*
7887c478bd9Sstevel@tonic-gate 	 * This next section is modified to allow for NIS passwd file
7897c478bd9Sstevel@tonic-gate 	 * conventions.  In the case where a password entry was being
7907c478bd9Sstevel@tonic-gate 	 * added to the password file, the original AT&T code read
7917c478bd9Sstevel@tonic-gate 	 * the entire password file in, noted any information needed, and
7927c478bd9Sstevel@tonic-gate 	 * copied the entries to a temporary file.  Then the new entry
7937c478bd9Sstevel@tonic-gate 	 * was added to the temporary file, and the temporary file was
7947c478bd9Sstevel@tonic-gate 	 * moved to be the real password file.
7957c478bd9Sstevel@tonic-gate 	 *
7967c478bd9Sstevel@tonic-gate 	 * The problem is, that with NIS compatability, we want to add new
7977c478bd9Sstevel@tonic-gate 	 * entries BEFORE the first NIS-referrant entry, so as not to have
7987c478bd9Sstevel@tonic-gate 	 * any surprises.  To accomplish this without extensively modifying
7997c478bd9Sstevel@tonic-gate 	 * the logic of the code below, as soon as a NIS-referrant entry is
8007c478bd9Sstevel@tonic-gate 	 * found we stop copying entries to the TEMP file and instead we
8017c478bd9Sstevel@tonic-gate 	 * remember
8027c478bd9Sstevel@tonic-gate 	 * the first NIS entry and where we found it, scan the rest of the
8037c478bd9Sstevel@tonic-gate 	 * password file without copying entries, then write the new entry, copy
8047c478bd9Sstevel@tonic-gate 	 * the stored password entry, then copy the rest of the password file.
8057c478bd9Sstevel@tonic-gate 	 */
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	error = 0;
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
8117c478bd9Sstevel@tonic-gate 		rid_tmpf();
8127c478bd9Sstevel@tonic-gate 		if (errno == ENOENT)
8137c478bd9Sstevel@tonic-gate 			bad_news();
8147c478bd9Sstevel@tonic-gate 		else
8157c478bd9Sstevel@tonic-gate 			file_error();
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	NIS_entry_seen = 0;
8197c478bd9Sstevel@tonic-gate 	cur_pos = 0;
8207c478bd9Sstevel@tonic-gate 	/* The while loop for reading PASSWD entries */
8217c478bd9Sstevel@tonic-gate 	info_mask |= WRITE_P_ENTRY;
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	while (!end_of_file) {
8247c478bd9Sstevel@tonic-gate 		pw_ptr1p = fgetpwent(pwf);
8257c478bd9Sstevel@tonic-gate 		if (pw_ptr1p == NULL) {
8267c478bd9Sstevel@tonic-gate 			if (!feof(pwf)) {
8277c478bd9Sstevel@tonic-gate 				/* A real error - report it and exit */
8287c478bd9Sstevel@tonic-gate 				rid_tmpf();
8297c478bd9Sstevel@tonic-gate 				bad_pasf();
8307c478bd9Sstevel@tonic-gate 			}
8317c478bd9Sstevel@tonic-gate 			else
8327c478bd9Sstevel@tonic-gate 				break;
8337c478bd9Sstevel@tonic-gate 		}
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 		if (!NIS_entry_seen)
8367c478bd9Sstevel@tonic-gate 			info_mask |= WRITE_P_ENTRY;
8377c478bd9Sstevel@tonic-gate 		else
8387c478bd9Sstevel@tonic-gate 			info_mask &= ~WRITE_P_ENTRY;
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 		/*
8417c478bd9Sstevel@tonic-gate 		 * Set up the uid usage blocks to find the first
8427c478bd9Sstevel@tonic-gate 		 * available uid above UID_MIN, if needed
8437c478bd9Sstevel@tonic-gate 		 */
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 		if (info_mask & NEED_DEF_UID)
8467c478bd9Sstevel@tonic-gate 			add_uid(pw_ptr1p->pw_uid);
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 		/* Check for unique UID */
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 		if (strcmp(lognamp, pw_ptr1p->pw_name) &&
8517c478bd9Sstevel@tonic-gate 		    (pw_ptr1p->pw_uid == passwd_st.pw_uid) &&
8527c478bd9Sstevel@tonic-gate 		    ((optn_mask & U_MASK) && !(optn_mask & O_MASK))) {
8537c478bd9Sstevel@tonic-gate 			rid_tmpf();		/* get rid of temp files */
8547c478bd9Sstevel@tonic-gate 			bad_uid();
8557c478bd9Sstevel@tonic-gate 		}
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 		/* Check for unique new logname */
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 		if (strcmp(lognamp, pw_ptr1p->pw_name) == 0 &&
8607c478bd9Sstevel@tonic-gate 		    optn_mask & L_MASK &&
8617c478bd9Sstevel@tonic-gate 		    strcmp(pw_ptr1p->pw_name, passwd_st.pw_name) == 0) {
8627c478bd9Sstevel@tonic-gate 			rid_tmpf();
8637c478bd9Sstevel@tonic-gate #ifdef att
8647c478bd9Sstevel@tonic-gate 			if (!getspnam(pw_ptr1p->pw_name))
8657c478bd9Sstevel@tonic-gate #else
8667c478bd9Sstevel@tonic-gate 			if (!local_getspnam(pw_ptr1p->pw_name))
8677c478bd9Sstevel@tonic-gate #endif
8687c478bd9Sstevel@tonic-gate 				bad_pasf();
8697c478bd9Sstevel@tonic-gate 			else
8707c478bd9Sstevel@tonic-gate 				bad_name("logname already exists");
8717c478bd9Sstevel@tonic-gate 		}
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 		if (strcmp(lognamp, pw_ptr1p->pw_name) == 0) {
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 			/* no good if we want to add an existing logname */
8767c478bd9Sstevel@tonic-gate 			if (optn_mask & A_MASK) {
8777c478bd9Sstevel@tonic-gate 				rid_tmpf();
8787c478bd9Sstevel@tonic-gate #ifdef att
8797c478bd9Sstevel@tonic-gate 				if (!getspnam(lognamp))
8807c478bd9Sstevel@tonic-gate #else
8817c478bd9Sstevel@tonic-gate 				if (!local_getspnam(lognamp))
8827c478bd9Sstevel@tonic-gate #endif
8837c478bd9Sstevel@tonic-gate 					bad_pasf();
8847c478bd9Sstevel@tonic-gate 				else
8857c478bd9Sstevel@tonic-gate 					bad_name("name already exists");
8867c478bd9Sstevel@tonic-gate 			}
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 			/* remember we found it */
8897c478bd9Sstevel@tonic-gate 			info_mask |= FOUND;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 			/* Do not write it out on the fly */
8927c478bd9Sstevel@tonic-gate 			if (optn_mask & D_MASK)
8937c478bd9Sstevel@tonic-gate 				info_mask &= ~WRITE_P_ENTRY;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 			if (optn_mask & M_MASK) {
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate #ifdef att
8987c478bd9Sstevel@tonic-gate 				if (!getspnam(lognamp))
8997c478bd9Sstevel@tonic-gate #else
9007c478bd9Sstevel@tonic-gate 				if (!local_getspnam(lognamp))
9017c478bd9Sstevel@tonic-gate #endif
9027c478bd9Sstevel@tonic-gate 				{
9037c478bd9Sstevel@tonic-gate 					rid_tmpf();
9047c478bd9Sstevel@tonic-gate 					bad_pasf();
9057c478bd9Sstevel@tonic-gate 				}
9067c478bd9Sstevel@tonic-gate 				if (optn_mask & L_MASK)
9077c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_name = passwd_st.pw_name;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 				if (optn_mask & U_MASK)
9107c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_uid = passwd_st.pw_uid;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 				if (optn_mask & G_MASK)
9137c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_gid = passwd_st.pw_gid;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 				if (optn_mask & C_MASK) {
9167c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_comment =
9177c478bd9Sstevel@tonic-gate 					    passwd_st.pw_comment;
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_gecos =
9207c478bd9Sstevel@tonic-gate 					    passwd_st.pw_comment;
9217c478bd9Sstevel@tonic-gate 				}
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 				if (optn_mask & H_MASK)
9247c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_dir = passwd_st.pw_dir;
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 				if (optn_mask & S_MASK)
9277c478bd9Sstevel@tonic-gate 					pw_ptr1p->pw_shell = passwd_st.pw_shell;
9287c478bd9Sstevel@tonic-gate 				ck_p_sz(pw_ptr1p);  /* check entry size */
9297c478bd9Sstevel@tonic-gate 			}
9307c478bd9Sstevel@tonic-gate 		}
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 		if (optn_mask & A_MASK) {
9337c478bd9Sstevel@tonic-gate 			if (!NIS_entry_seen) {
9347c478bd9Sstevel@tonic-gate 				char	*p;
9357c478bd9Sstevel@tonic-gate 				p  = strchr("+-", pw_ptr1p->pw_name[0]);
9367c478bd9Sstevel@tonic-gate 				if (p != NULL) {
9377c478bd9Sstevel@tonic-gate 					/*
9387c478bd9Sstevel@tonic-gate 					 * Found first NIS entry.
9397c478bd9Sstevel@tonic-gate 					 * so remember it.
9407c478bd9Sstevel@tonic-gate 					 */
9417c478bd9Sstevel@tonic-gate 					NIS_pos = cur_pos;
9427c478bd9Sstevel@tonic-gate 					NIS_entry_seen = 1;
9437c478bd9Sstevel@tonic-gate 					info_mask &= ~WRITE_P_ENTRY;
9447c478bd9Sstevel@tonic-gate 				}
9457c478bd9Sstevel@tonic-gate 				else
9467c478bd9Sstevel@tonic-gate 					cur_pos = ftell(pwf);
9477c478bd9Sstevel@tonic-gate 			}
9487c478bd9Sstevel@tonic-gate 		}
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 		if (info_mask & WRITE_P_ENTRY) {
9517c478bd9Sstevel@tonic-gate 			if (putpwent(pw_ptr1p, fp_ptemp)) {
9527c478bd9Sstevel@tonic-gate 				rid_tmpf();
9537c478bd9Sstevel@tonic-gate 				file_error();
9547c478bd9Sstevel@tonic-gate 			}
9557c478bd9Sstevel@tonic-gate 		}
9567c478bd9Sstevel@tonic-gate 	} /* end-of-while-loop */
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	if (error >= 1) {
9597c478bd9Sstevel@tonic-gate 		msg = "%s: Bad entry found in /etc/passwd.  Run pwconv.\n";
9607c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext(msg), prognamp);
9617c478bd9Sstevel@tonic-gate 	}
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	/* Cannot find the target entry and we are deleting or modifying */
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) {
9667c478bd9Sstevel@tonic-gate 		rid_tmpf();
9677c478bd9Sstevel@tonic-gate #ifdef att
9687c478bd9Sstevel@tonic-gate 		if (getspnam(lognamp) != NULL)
9697c478bd9Sstevel@tonic-gate #else
9707c478bd9Sstevel@tonic-gate 		if (local_getspnam(lognamp) != NULL)
9717c478bd9Sstevel@tonic-gate #endif
9727c478bd9Sstevel@tonic-gate 			bad_pasf();
9737c478bd9Sstevel@tonic-gate 		else
9747c478bd9Sstevel@tonic-gate 			bad_name("name does not exist");
9757c478bd9Sstevel@tonic-gate 	}
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	/* First available uid above UID_MIN is ... */
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	if (info_mask & NEED_DEF_UID)
9807c478bd9Sstevel@tonic-gate 		passwd_st.pw_uid = uid_sp->high + 1;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	/* Write out the added entry now */
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	if (optn_mask & A_MASK) {
9857c478bd9Sstevel@tonic-gate 		ck_p_sz(&passwd_st);	/* Check entry size */
9867c478bd9Sstevel@tonic-gate 		if (putpwent(&passwd_st, fp_ptemp)) {
9877c478bd9Sstevel@tonic-gate 			rid_tmpf();
9887c478bd9Sstevel@tonic-gate 			file_error();
9897c478bd9Sstevel@tonic-gate 		}
9907c478bd9Sstevel@tonic-gate 		/*
9917c478bd9Sstevel@tonic-gate 		 * Now put out the rest of the password file, if needed.
9927c478bd9Sstevel@tonic-gate 		 */
9937c478bd9Sstevel@tonic-gate 		if (NIS_entry_seen) {
9947c478bd9Sstevel@tonic-gate 			int n;
9957c478bd9Sstevel@tonic-gate 			char buf[1024];
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 			if (fseek(pwf, NIS_pos, SEEK_SET) < 0) {
9987c478bd9Sstevel@tonic-gate 				rid_tmpf();
9997c478bd9Sstevel@tonic-gate 				file_error();
10007c478bd9Sstevel@tonic-gate 			}
10017c478bd9Sstevel@tonic-gate 			while ((n = fread(buf, sizeof (char), 1024, pwf)) > 0) {
10027c478bd9Sstevel@tonic-gate 				if (fwrite(buf, sizeof (char), n, fp_ptemp)
10037c478bd9Sstevel@tonic-gate 				    != n) {
10047c478bd9Sstevel@tonic-gate 					rid_tmpf();
10057c478bd9Sstevel@tonic-gate 					file_error();
10067c478bd9Sstevel@tonic-gate 				}
10077c478bd9Sstevel@tonic-gate 			}
10087c478bd9Sstevel@tonic-gate 		}
10097c478bd9Sstevel@tonic-gate 	}
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 	(void) fclose(pwf);
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	/* flush and sync the file before closing it */
10147c478bd9Sstevel@tonic-gate 	if (fflush(fp_ptemp) != 0 || fsync(fd_ptemp) != 0)
10157c478bd9Sstevel@tonic-gate 		file_error();
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	/* Now we are done with PASSWD */
10187c478bd9Sstevel@tonic-gate 	(void) fclose(fp_ptemp);
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	/* Do this if we are touching both password files */
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	if (info_mask & BOTH_FILES) {
10247c478bd9Sstevel@tonic-gate 		info_mask &= ~FOUND;		/* Reset FOUND flag */
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 		/* The while loop for reading SHADOW entries */
10277c478bd9Sstevel@tonic-gate 		info_mask |= WRITE_S_ENTRY;
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 		end_of_file = 0;
10307c478bd9Sstevel@tonic-gate 		errno = 0;
10317c478bd9Sstevel@tonic-gate 		error = 0;
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 		NIS_entry_seen = 0;
10347c478bd9Sstevel@tonic-gate 		cur_pos = 0;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 		if ((spf = fopen("/etc/shadow", "r")) == NULL) {
10377c478bd9Sstevel@tonic-gate 			rid_tmpf();
10387c478bd9Sstevel@tonic-gate 			file_error();
10397c478bd9Sstevel@tonic-gate 		}
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 		while (!end_of_file) {
10427c478bd9Sstevel@tonic-gate 			sp_ptr1p = fgetspent(spf);
10437c478bd9Sstevel@tonic-gate 			if (sp_ptr1p == NULL) {
10447c478bd9Sstevel@tonic-gate 				if (!feof(spf)) {
10457c478bd9Sstevel@tonic-gate 					rid_tmpf();
10467c478bd9Sstevel@tonic-gate 					bad_pasf();
10477c478bd9Sstevel@tonic-gate 				}
10487c478bd9Sstevel@tonic-gate 				else
10497c478bd9Sstevel@tonic-gate 					break;
10507c478bd9Sstevel@tonic-gate 			}
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 			if (!NIS_entry_seen)
10537c478bd9Sstevel@tonic-gate 				info_mask |= WRITE_S_ENTRY;
10547c478bd9Sstevel@tonic-gate 			else
10557c478bd9Sstevel@tonic-gate 				info_mask &= ~WRITE_S_ENTRY;
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 			/*
10587c478bd9Sstevel@tonic-gate 			 * See if the new logname already exist in the
10597c478bd9Sstevel@tonic-gate 			 * shadow passwd file
10607c478bd9Sstevel@tonic-gate 			 */
10617c478bd9Sstevel@tonic-gate 			if ((optn_mask & M_MASK) &&
10627c478bd9Sstevel@tonic-gate 			    strcmp(lognamp, shadow_st.sp_namp) != 0 &&
10637c478bd9Sstevel@tonic-gate 			    strcmp(sp_ptr1p->sp_namp, shadow_st.sp_namp) == 0) {
10647c478bd9Sstevel@tonic-gate 				rid_tmpf();
10657c478bd9Sstevel@tonic-gate 				bad_pasf();
10667c478bd9Sstevel@tonic-gate 			}
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 			if (strcmp(lognamp, sp_ptr1p->sp_namp) == 0) {
10697c478bd9Sstevel@tonic-gate 				info_mask |= FOUND;
10707c478bd9Sstevel@tonic-gate 				if (optn_mask & A_MASK) {
10717c478bd9Sstevel@tonic-gate 					/* password file inconsistent */
10727c478bd9Sstevel@tonic-gate 					rid_tmpf();
10737c478bd9Sstevel@tonic-gate 					bad_pasf();
10747c478bd9Sstevel@tonic-gate 				}
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 				if (optn_mask & M_MASK) {
10777c478bd9Sstevel@tonic-gate 					sp_ptr1p->sp_namp = shadow_st.sp_namp;
10787c478bd9Sstevel@tonic-gate 					if (F_MASK & optn_mask)
10797c478bd9Sstevel@tonic-gate 						sp_ptr1p->sp_inact =
10807c478bd9Sstevel@tonic-gate 						    shadow_st.sp_inact;
10817c478bd9Sstevel@tonic-gate 					if (E_MASK & optn_mask)
10827c478bd9Sstevel@tonic-gate 						sp_ptr1p->sp_expire =
10837c478bd9Sstevel@tonic-gate 						    shadow_st.sp_expire;
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 					ck_s_sz(sp_ptr1p);
10867c478bd9Sstevel@tonic-gate 				}
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 				if (optn_mask & D_MASK)
10897c478bd9Sstevel@tonic-gate 					info_mask &= ~WRITE_S_ENTRY;
10907c478bd9Sstevel@tonic-gate 			}
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 			if (optn_mask & A_MASK) {
10937c478bd9Sstevel@tonic-gate 				if (!NIS_entry_seen) {
10947c478bd9Sstevel@tonic-gate 					char	*p;
10957c478bd9Sstevel@tonic-gate 					p = strchr("+-", sp_ptr1p->sp_namp[0]);
10967c478bd9Sstevel@tonic-gate 					if (p != NULL) {
10977c478bd9Sstevel@tonic-gate 						/*
10987c478bd9Sstevel@tonic-gate 						 * Found first NIS entry.
10997c478bd9Sstevel@tonic-gate 						 * so remember it.
11007c478bd9Sstevel@tonic-gate 						 */
11017c478bd9Sstevel@tonic-gate 						NIS_pos = cur_pos;
11027c478bd9Sstevel@tonic-gate 						NIS_entry_seen = 1;
11037c478bd9Sstevel@tonic-gate 						info_mask &= ~WRITE_S_ENTRY;
11047c478bd9Sstevel@tonic-gate 					}
11057c478bd9Sstevel@tonic-gate 					else
11067c478bd9Sstevel@tonic-gate 						cur_pos = ftell(spf);
11077c478bd9Sstevel@tonic-gate 				}
11087c478bd9Sstevel@tonic-gate 			}
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 			if (info_mask & WRITE_S_ENTRY) {
11117c478bd9Sstevel@tonic-gate 				if (putspent(sp_ptr1p, fp_stemp)) {
11127c478bd9Sstevel@tonic-gate 					rid_tmpf();
11137c478bd9Sstevel@tonic-gate 					file_error();
11147c478bd9Sstevel@tonic-gate 				}
11157c478bd9Sstevel@tonic-gate 			}
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 		} /* end-of-while-loop */
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 		if (error >= 1) {
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 			msg = BAD_ENT_MESSAGE;
11227c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext(msg), prognamp);
11237c478bd9Sstevel@tonic-gate 		}
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 		/*
11267c478bd9Sstevel@tonic-gate 		 * If we cannot find the entry and we are deleting or
11277c478bd9Sstevel@tonic-gate 		 *  modifying
11287c478bd9Sstevel@tonic-gate 		 */
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 		if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) {
11317c478bd9Sstevel@tonic-gate 			rid_tmpf();
11327c478bd9Sstevel@tonic-gate 			bad_pasf();
11337c478bd9Sstevel@tonic-gate 		}
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 		if (optn_mask & A_MASK) {
11367c478bd9Sstevel@tonic-gate 			ck_s_sz(&shadow_st);
11377c478bd9Sstevel@tonic-gate 			if (putspent(&shadow_st, fp_stemp)) {
11387c478bd9Sstevel@tonic-gate 				rid_tmpf();
11397c478bd9Sstevel@tonic-gate 				file_error();
11407c478bd9Sstevel@tonic-gate 			}
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 			/*
11437c478bd9Sstevel@tonic-gate 			 * Now put out the rest of the shadow file, if needed.
11447c478bd9Sstevel@tonic-gate 			 */
11457c478bd9Sstevel@tonic-gate 			if (NIS_entry_seen) {
11467c478bd9Sstevel@tonic-gate 				file_copy(spf, NIS_pos);
11477c478bd9Sstevel@tonic-gate 			}
11487c478bd9Sstevel@tonic-gate 		}
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		/* flush and sync the file before closing it */
11517c478bd9Sstevel@tonic-gate 		if (fflush(fp_stemp) != 0 || fsync(fd_stemp) != 0)
11527c478bd9Sstevel@tonic-gate 			file_error();
11537c478bd9Sstevel@tonic-gate 		(void) fclose(fp_stemp);
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 		/* Done with SHADOW */
11567c478bd9Sstevel@tonic-gate 		(void) fclose(spf);
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	} /* End of if info_mask */
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	if (info_mask & UATTR_FILE) {
11617c478bd9Sstevel@tonic-gate 		info_mask &= ~FOUND;		/* Reset FOUND flag */
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 		/* The while loop for reading USER_ATTR entries */
11647c478bd9Sstevel@tonic-gate 		info_mask |= WRITE_S_ENTRY;
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 		end_of_file = 0;
11677c478bd9Sstevel@tonic-gate 		errno = 0;
11687c478bd9Sstevel@tonic-gate 		error = 0;
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 		NIS_entry_seen = 0;
11717c478bd9Sstevel@tonic-gate 		cur_pos = 0;
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 		if ((uaf = fopen(USERATTR_FILENAME, "r")) == NULL) {
11747c478bd9Sstevel@tonic-gate 			rid_tmpf();
11757c478bd9Sstevel@tonic-gate 			file_error();
11767c478bd9Sstevel@tonic-gate 		}
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 		while (!end_of_file) {
11797c478bd9Sstevel@tonic-gate 			ua_ptr1p = fgetuserattr(uaf);
11807c478bd9Sstevel@tonic-gate 			if (ua_ptr1p == NULL) {
11817c478bd9Sstevel@tonic-gate 				if (!feof(uaf)) {
11827c478bd9Sstevel@tonic-gate 					rid_tmpf();
11837c478bd9Sstevel@tonic-gate 					bad_uattr();
11847c478bd9Sstevel@tonic-gate 				}
11857c478bd9Sstevel@tonic-gate 				else
11867c478bd9Sstevel@tonic-gate 					break;
11877c478bd9Sstevel@tonic-gate 			}
11887c478bd9Sstevel@tonic-gate 
11897c478bd9Sstevel@tonic-gate 			if (ua_ptr1p->name[0] == '#') {
11907c478bd9Sstevel@tonic-gate 				/*
11917c478bd9Sstevel@tonic-gate 				 * If this is a comment, write it back as it
11927c478bd9Sstevel@tonic-gate 				 * is.
11937c478bd9Sstevel@tonic-gate 				 */
11947c478bd9Sstevel@tonic-gate 				if (ua_ptr1p->qualifier[0] == '\0' &&
11957c478bd9Sstevel@tonic-gate 				    ua_ptr1p->res1[0] == '\0' &&
11967c478bd9Sstevel@tonic-gate 				    ua_ptr1p->res2[0] == '\0' &&
11977c478bd9Sstevel@tonic-gate 				    (ua_ptr1p->attr == NULL ||
11987c478bd9Sstevel@tonic-gate 				    ua_ptr1p->attr->length == 0))
11997c478bd9Sstevel@tonic-gate 					(void) fprintf(fp_uatemp, "%s\n",
12007c478bd9Sstevel@tonic-gate 					    ua_ptr1p->name);
12017c478bd9Sstevel@tonic-gate 				else
12027c478bd9Sstevel@tonic-gate 					/*
12037c478bd9Sstevel@tonic-gate 					 * This is a commented user_attr entry;
12047c478bd9Sstevel@tonic-gate 					 * reformat it, and write it back.
12057c478bd9Sstevel@tonic-gate 					 */
12067c478bd9Sstevel@tonic-gate 					putuserattrent(ua_ptr1p, fp_uatemp);
12077c478bd9Sstevel@tonic-gate 				free_userattr(ua_ptr1p);
12087c478bd9Sstevel@tonic-gate 				continue;
12097c478bd9Sstevel@tonic-gate 			}
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 			if (!NIS_entry_seen)
12127c478bd9Sstevel@tonic-gate 				info_mask |= WRITE_S_ENTRY;
12137c478bd9Sstevel@tonic-gate 			else
12147c478bd9Sstevel@tonic-gate 				info_mask &= ~WRITE_S_ENTRY;
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 			/*
12177c478bd9Sstevel@tonic-gate 			 * See if the new logname already exist in the
12187c478bd9Sstevel@tonic-gate 			 * user_attr file
12197c478bd9Sstevel@tonic-gate 			 */
12207c478bd9Sstevel@tonic-gate 			if ((optn_mask & M_MASK) &&
12217c478bd9Sstevel@tonic-gate 			    strcmp(lognamp, userattr_st.name) != 0 &&
12227c478bd9Sstevel@tonic-gate 			    strcmp(ua_ptr1p->name, userattr_st.name) == 0) {
12237c478bd9Sstevel@tonic-gate 				rid_tmpf();
12247c478bd9Sstevel@tonic-gate 				bad_pasf();
12257c478bd9Sstevel@tonic-gate 			}
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 			if (strcmp(lognamp, ua_ptr1p->name) == 0) {
12287c478bd9Sstevel@tonic-gate 				info_mask |= FOUND;
12297c478bd9Sstevel@tonic-gate 				if (optn_mask & A_MASK) {
12307c478bd9Sstevel@tonic-gate 					/* password file inconsistent */
12317c478bd9Sstevel@tonic-gate 					rid_tmpf();
12327c478bd9Sstevel@tonic-gate 					bad_pasf();
12337c478bd9Sstevel@tonic-gate 				}
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 				if (optn_mask & M_MASK) {
12367c478bd9Sstevel@tonic-gate 					int	j;
12377c478bd9Sstevel@tonic-gate 					char	*value;
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 					for (j = 0; j < UA_KEYS; j++) {
12407c478bd9Sstevel@tonic-gate 						if (ua_opts[j].newvalue != NULL)
12417c478bd9Sstevel@tonic-gate 							continue;
12427c478bd9Sstevel@tonic-gate 						value =
12437c478bd9Sstevel@tonic-gate 						    kva_match(ua_ptr1p->attr,
12447c478bd9Sstevel@tonic-gate 						    (char *)ua_opts[j].key);
12457c478bd9Sstevel@tonic-gate 						if (value == NULL)
12467c478bd9Sstevel@tonic-gate 							continue;
12477c478bd9Sstevel@tonic-gate 						assign_attr(&userattr_st,
12487c478bd9Sstevel@tonic-gate 						    ua_opts[j].key,
12497c478bd9Sstevel@tonic-gate 						    value);
12507c478bd9Sstevel@tonic-gate 					}
12517c478bd9Sstevel@tonic-gate 					free_userattr(ua_ptr1p);
12527c478bd9Sstevel@tonic-gate 					ua_ptr1p = &userattr_st;
12537c478bd9Sstevel@tonic-gate 				}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 				if (optn_mask & D_MASK)
12567c478bd9Sstevel@tonic-gate 					info_mask &= ~WRITE_S_ENTRY;
12577c478bd9Sstevel@tonic-gate 			} else if (optn_mask & D_MASK) {
12587c478bd9Sstevel@tonic-gate 				char *rolelist;
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 				rolelist = kva_match(ua_ptr1p->attr,
12617c478bd9Sstevel@tonic-gate 				    USERATTR_ROLES_KW);
12627c478bd9Sstevel@tonic-gate 				if (rolelist) {
12637c478bd9Sstevel@tonic-gate 					unassign_role(ua_ptr1p,
12647c478bd9Sstevel@tonic-gate 					    rolelist, lognamp);
12657c478bd9Sstevel@tonic-gate 				}
12667c478bd9Sstevel@tonic-gate 			}
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 			if (info_mask & WRITE_S_ENTRY) {
12697c478bd9Sstevel@tonic-gate 				putuserattrent(ua_ptr1p, fp_uatemp);
12707c478bd9Sstevel@tonic-gate 			}
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 			if (!(optn_mask & M_MASK))
12737c478bd9Sstevel@tonic-gate 				free_userattr(ua_ptr1p);
12747c478bd9Sstevel@tonic-gate 		} /* end-of-while-loop */
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 		if (error >= 1) {
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 			msg = BAD_ENT_MESSAGE;
12797c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext(msg), prognamp);
12807c478bd9Sstevel@tonic-gate 		}
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 		/*
12837c478bd9Sstevel@tonic-gate 		 * Add entry in user_attr if masks is UATTR_MASK
12847c478bd9Sstevel@tonic-gate 		 * We don't need to do anything for L_MASK if there's
12857c478bd9Sstevel@tonic-gate 		 * no user_attr entry for the user being modified.
12867c478bd9Sstevel@tonic-gate 		 */
12877c478bd9Sstevel@tonic-gate 		if (!(info_mask & FOUND) && !(L_MASK & optn_mask) &&
12887c478bd9Sstevel@tonic-gate 		    !(D_MASK & optn_mask)) {
12897c478bd9Sstevel@tonic-gate 			putuserattrent(&userattr_st, fp_uatemp);
12907c478bd9Sstevel@tonic-gate 		}
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 		/* flush and sync the file before closing it */
12937c478bd9Sstevel@tonic-gate 		if (fflush(fp_uatemp) != 0 || fsync(fd_uatemp) != 0)
12947c478bd9Sstevel@tonic-gate 			file_error();
12957c478bd9Sstevel@tonic-gate 		(void) fclose(fp_uatemp);
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate 		/* Done with USERATTR */
12987c478bd9Sstevel@tonic-gate 		(void) fclose(uaf);
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 	} /* End of if info_mask */
13017c478bd9Sstevel@tonic-gate 	/* ignore all signals */
13027c478bd9Sstevel@tonic-gate 
13037c478bd9Sstevel@tonic-gate 	for (i = 1; i < NSIG; i++)
13047c478bd9Sstevel@tonic-gate 		(void) sigset(i, SIG_IGN);
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 	errno = 0;		/* For correcting sigset to SIGKILL */
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 	if (unlink(OPASSWD) && access(OPASSWD, 0) == 0)
13097c478bd9Sstevel@tonic-gate 		file_error();
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	if (link(PASSWD, OPASSWD) == -1)
13127c478bd9Sstevel@tonic-gate 			file_error();
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 	if (rename(PASSTEMP, PASSWD) == -1) {
13167c478bd9Sstevel@tonic-gate 		if (link(OPASSWD, PASSWD))
13177c478bd9Sstevel@tonic-gate 			bad_news();
13187c478bd9Sstevel@tonic-gate 		file_error();
13197c478bd9Sstevel@tonic-gate 	}
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 	if (info_mask & BOTH_FILES) {
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 		if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) {
13257c478bd9Sstevel@tonic-gate 			if (rec_pwd())
13267c478bd9Sstevel@tonic-gate 				bad_news();
13277c478bd9Sstevel@tonic-gate 			else
13287c478bd9Sstevel@tonic-gate 				file_error();
13297c478bd9Sstevel@tonic-gate 		}
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 		if (link(SHADOW, OSHADOW) == -1) {
13327c478bd9Sstevel@tonic-gate 			if (rec_pwd())
13337c478bd9Sstevel@tonic-gate 				bad_news();
13347c478bd9Sstevel@tonic-gate 			else
13357c478bd9Sstevel@tonic-gate 				file_error();
13367c478bd9Sstevel@tonic-gate 		}
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 		if (rename(SHADTEMP, SHADOW) == -1) {
13407c478bd9Sstevel@tonic-gate 			if (rename(OSHADOW, SHADOW) == -1)
13417c478bd9Sstevel@tonic-gate 				bad_news();
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 			if (rec_pwd())
13447c478bd9Sstevel@tonic-gate 				bad_news();
13457c478bd9Sstevel@tonic-gate 			else
13467c478bd9Sstevel@tonic-gate 				file_error();
13477c478bd9Sstevel@tonic-gate 		}
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	}
13507c478bd9Sstevel@tonic-gate 	if (info_mask & UATTR_FILE) {
13517c478bd9Sstevel@tonic-gate 		if (unlink(OUSERATTR_FILENAME) &&
13527c478bd9Sstevel@tonic-gate 		    access(OUSERATTR_FILENAME, 0) == 0) {
13537c478bd9Sstevel@tonic-gate 			if (rec_pwd())
13547c478bd9Sstevel@tonic-gate 				bad_news();
13557c478bd9Sstevel@tonic-gate 			else
13567c478bd9Sstevel@tonic-gate 				file_error();
13577c478bd9Sstevel@tonic-gate 		}
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 		if (link(USERATTR_FILENAME, OUSERATTR_FILENAME) == -1) {
13607c478bd9Sstevel@tonic-gate 			if (rec_pwd())
13617c478bd9Sstevel@tonic-gate 				bad_news();
13627c478bd9Sstevel@tonic-gate 			else
13637c478bd9Sstevel@tonic-gate 				file_error();
13647c478bd9Sstevel@tonic-gate 		}
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 		if (rename(USERATTR_TEMP, USERATTR_FILENAME) == -1) {
13687c478bd9Sstevel@tonic-gate 			if (rename(OUSERATTR_FILENAME, USERATTR_FILENAME) == -1)
13697c478bd9Sstevel@tonic-gate 				bad_news();
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 			if (rec_pwd())
13727c478bd9Sstevel@tonic-gate 				bad_news();
13737c478bd9Sstevel@tonic-gate 			else
13747c478bd9Sstevel@tonic-gate 				file_error();
13757c478bd9Sstevel@tonic-gate 		}
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate 	}
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 	ulckpwdf();
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	/*
13827c478bd9Sstevel@tonic-gate 	 * Return 0 status, indicating success
13837c478bd9Sstevel@tonic-gate 	 */
138449335bdeSbasabi 	return (0);
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate }  /* end of main */
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate /* Try to recover the old password file */
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate int
139149335bdeSbasabi rec_pwd(void)
13927c478bd9Sstevel@tonic-gate {
13937c478bd9Sstevel@tonic-gate 	if (unlink(PASSWD) || link(OPASSWD, PASSWD))
13947c478bd9Sstevel@tonic-gate 		return (-1);
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 	return (0);
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate /* combine two uid_blk's */
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate void
140249335bdeSbasabi uid_bcom(struct uid_blk *uid_p)
14037c478bd9Sstevel@tonic-gate {
14047c478bd9Sstevel@tonic-gate 	struct uid_blk *uid_tp;
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	uid_tp = uid_p->link;
14077c478bd9Sstevel@tonic-gate 	uid_p->high = uid_tp->high;
14087c478bd9Sstevel@tonic-gate 	uid_p->link = uid_tp->link;
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 	free(uid_tp);
14117c478bd9Sstevel@tonic-gate }
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate /* add a new uid_blk */
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate void
141649335bdeSbasabi add_ublk(uid_t num, struct uid_blk *uid_p)
14177c478bd9Sstevel@tonic-gate {
14187c478bd9Sstevel@tonic-gate 	struct uid_blk *uid_tp;
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 	uid_tp = malloc(sizeof (struct uid_blk));
14217c478bd9Sstevel@tonic-gate 	if (uid_tp == NULL) {
14227c478bd9Sstevel@tonic-gate 		rid_tmpf();
14237c478bd9Sstevel@tonic-gate 		file_error();
14247c478bd9Sstevel@tonic-gate 	}
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate 	uid_tp->high = uid_tp->low = num;
14277c478bd9Sstevel@tonic-gate 	uid_tp->link = uid_p->link;
14287c478bd9Sstevel@tonic-gate 	uid_p->link = uid_tp;
14297c478bd9Sstevel@tonic-gate }
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate /*
14327c478bd9Sstevel@tonic-gate  *	Here we are using a linked list of uid_blk to keep track of all
14337c478bd9Sstevel@tonic-gate  *	the used uids.	Each uid_blk represents a range of used uid,
14347c478bd9Sstevel@tonic-gate  *	with low represents the low inclusive end and high represents
14357c478bd9Sstevel@tonic-gate  *	the high inclusive end.  In the beginning, we initialize a linked
14367c478bd9Sstevel@tonic-gate  *	list of one uid_blk with low = high = (UID_MIN-1).  This was
14377c478bd9Sstevel@tonic-gate  *	done in main().
14387c478bd9Sstevel@tonic-gate  *	Each time we read in another used uid, we add it onto the linked
14397c478bd9Sstevel@tonic-gate  *	list by either making a new uid_blk, decrementing the low of
14407c478bd9Sstevel@tonic-gate  *	an existing uid_blk, incrementing the high of an existing
14417c478bd9Sstevel@tonic-gate  *	uid_blk, or combining two existing uid_blks.  After we finished
14427c478bd9Sstevel@tonic-gate  *	building this linked list, the first available uid above or
14437c478bd9Sstevel@tonic-gate  *	equal to UID_MIN is the high of the first uid_blk in the linked
14447c478bd9Sstevel@tonic-gate  *	list + 1.
14457c478bd9Sstevel@tonic-gate  */
14467c478bd9Sstevel@tonic-gate /* add_uid() adds uid to the link list of used uids */
14477c478bd9Sstevel@tonic-gate void
144849335bdeSbasabi add_uid(uid_t uid)
14497c478bd9Sstevel@tonic-gate {
14507c478bd9Sstevel@tonic-gate 	struct uid_blk *uid_p;
14517c478bd9Sstevel@tonic-gate 	/* Only keep track of the ones above UID_MIN */
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	if (uid >= UID_MIN) {
14547c478bd9Sstevel@tonic-gate 		uid_p = uid_sp;
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 		while (uid_p != NULL) {
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 			if (uid_p->link != NULL) {
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 				if (uid >= uid_p->link->low)
14617c478bd9Sstevel@tonic-gate 					uid_p = uid_p->link;
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 				else if (uid >= uid_p->low &&
14647c478bd9Sstevel@tonic-gate 				    uid <= uid_p->high) {
14657c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14667c478bd9Sstevel@tonic-gate 				}
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 				else if (uid == (uid_p->high+1)) {
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 					if (++uid_p->high ==
14717c478bd9Sstevel@tonic-gate 					    (uid_p->link->low - 1)) {
14727c478bd9Sstevel@tonic-gate 						uid_bcom(uid_p);
14737c478bd9Sstevel@tonic-gate 					}
14747c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14757c478bd9Sstevel@tonic-gate 				}
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate 				else if (uid == (uid_p->link->low - 1)) {
14787c478bd9Sstevel@tonic-gate 					uid_p->link->low --;
14797c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14807c478bd9Sstevel@tonic-gate 				}
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 				else if (uid < uid_p->link->low) {
14837c478bd9Sstevel@tonic-gate 					add_ublk(uid, uid_p);
14847c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14857c478bd9Sstevel@tonic-gate 				}
14867c478bd9Sstevel@tonic-gate 			} /* if uid_p->link */
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate 			else {
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 				if (uid == (uid_p->high + 1)) {
14917c478bd9Sstevel@tonic-gate 					uid_p->high++;
14927c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14937c478bd9Sstevel@tonic-gate 				} else if (uid >= uid_p->low &&
14947c478bd9Sstevel@tonic-gate 				    uid <= uid_p->high) {
14957c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14967c478bd9Sstevel@tonic-gate 				} else {
14977c478bd9Sstevel@tonic-gate 					add_ublk(uid, uid_p);
14987c478bd9Sstevel@tonic-gate 					uid_p = NULL;
14997c478bd9Sstevel@tonic-gate 				}
15007c478bd9Sstevel@tonic-gate 			} /* else */
15017c478bd9Sstevel@tonic-gate 		} /* while uid_p */
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 	} /* if uid */
15047c478bd9Sstevel@tonic-gate }
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate void
150749335bdeSbasabi bad_perm(void)
15087c478bd9Sstevel@tonic-gate {
15097c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("%s: Permission denied\n"), prognamp);
15107c478bd9Sstevel@tonic-gate 	exit(1);
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate void
151449335bdeSbasabi bad_usage(char *sp)
15157c478bd9Sstevel@tonic-gate {
15167c478bd9Sstevel@tonic-gate 	if (strlen(sp) != 0)
15177c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n", prognamp, gettext(sp));
15187c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Usage:\n\
15197c478bd9Sstevel@tonic-gate %s -a [-c comment] [-h homedir] [-u uid [-o]] [-g gid] \n\
15207c478bd9Sstevel@tonic-gate 	    [-s shell] [-f inactive] [-e expire] name\n\
15217c478bd9Sstevel@tonic-gate %s -m  -c comment | -h homedir | -u uid [-o] | -g gid |\n\
15227c478bd9Sstevel@tonic-gate 	    -s shell | -f inactive | -e expire	|  -l logname  name\n\
15237c478bd9Sstevel@tonic-gate %s -d name\n"), prognamp, prognamp, prognamp);
15247c478bd9Sstevel@tonic-gate 	if (info_mask & LOCKED)
15257c478bd9Sstevel@tonic-gate 		ulckpwdf();
15267c478bd9Sstevel@tonic-gate 	exit(2);
15277c478bd9Sstevel@tonic-gate }
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate void
153049335bdeSbasabi bad_arg(char *s)
15317c478bd9Sstevel@tonic-gate {
15327c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s));
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate 	if (info_mask & LOCKED)
15357c478bd9Sstevel@tonic-gate 		ulckpwdf();
15367c478bd9Sstevel@tonic-gate 	exit(3);
15377c478bd9Sstevel@tonic-gate }
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate void
154049335bdeSbasabi bad_name(char *s)
15417c478bd9Sstevel@tonic-gate {
15427c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s));
15437c478bd9Sstevel@tonic-gate 	ulckpwdf();
15447c478bd9Sstevel@tonic-gate 	exit(9);
15457c478bd9Sstevel@tonic-gate }
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate void
154849335bdeSbasabi bad_uid(void)
15497c478bd9Sstevel@tonic-gate {
15507c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("%s: UID in use\n"), prognamp);
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 	ulckpwdf();
15537c478bd9Sstevel@tonic-gate 	exit(4);
15547c478bd9Sstevel@tonic-gate }
15557c478bd9Sstevel@tonic-gate 
15567c478bd9Sstevel@tonic-gate void
155749335bdeSbasabi bad_pasf(void)
15587c478bd9Sstevel@tonic-gate {
15597c478bd9Sstevel@tonic-gate 	msg = "%s: Inconsistent password files\n";
15607c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(msg), prognamp);
15617c478bd9Sstevel@tonic-gate 
15627c478bd9Sstevel@tonic-gate 	ulckpwdf();
15637c478bd9Sstevel@tonic-gate 	exit(5);
15647c478bd9Sstevel@tonic-gate }
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate void
156749335bdeSbasabi bad_uattr(void)
15687c478bd9Sstevel@tonic-gate {
15697c478bd9Sstevel@tonic-gate 	msg = "%s: Bad user_attr database\n";
15707c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(msg), prognamp);
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 	ulckpwdf();
15737c478bd9Sstevel@tonic-gate 	exit(5);
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate void
157749335bdeSbasabi file_error(void)
15787c478bd9Sstevel@tonic-gate {
15797c478bd9Sstevel@tonic-gate 	msg = "%s: Unexpected failure.	Password files unchanged\n";
15807c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(msg), prognamp);
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate 	ulckpwdf();
15837c478bd9Sstevel@tonic-gate 	exit(6);
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate 
15867c478bd9Sstevel@tonic-gate void
158749335bdeSbasabi bad_news(void)
15887c478bd9Sstevel@tonic-gate {
15897c478bd9Sstevel@tonic-gate 	msg = "%s: Unexpected failure.	Password file(s) missing\n";
15907c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(msg), prognamp);
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	ulckpwdf();
15937c478bd9Sstevel@tonic-gate 	exit(7);
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate void
159749335bdeSbasabi no_lock(void)
15987c478bd9Sstevel@tonic-gate {
15997c478bd9Sstevel@tonic-gate 	msg = "%s: Password file(s) busy.  Try again later\n";
16007c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(msg), prognamp);
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate 	exit(8);
16037c478bd9Sstevel@tonic-gate }
16047c478bd9Sstevel@tonic-gate 
16057c478bd9Sstevel@tonic-gate /* Check for the size of the whole passwd entry */
16067c478bd9Sstevel@tonic-gate void
160749335bdeSbasabi ck_p_sz(struct passwd *pwp)
16087c478bd9Sstevel@tonic-gate {
16097c478bd9Sstevel@tonic-gate 	char ctp[128];
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	/* Ensure that the combined length of the individual */
16127c478bd9Sstevel@tonic-gate 	/* fields will fit in a passwd entry. The 1 accounts for the */
16137c478bd9Sstevel@tonic-gate 	/* newline and the 6 accounts for the colons (:'s) */
16147c478bd9Sstevel@tonic-gate 	if (((int)strlen(pwp->pw_name) + 1 +
16157c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", pwp->pw_uid) +
16167c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", pwp->pw_gid) +
16177c478bd9Sstevel@tonic-gate 	    (int)strlen(pwp->pw_comment) +
16187c478bd9Sstevel@tonic-gate 	    (int)strlen(pwp->pw_dir) +
16191316014bSbasabi 	    (int)strlen(pwp->pw_shell) + 6) > (ENTRY_LENGTH-1)) {
16207c478bd9Sstevel@tonic-gate 		rid_tmpf();
16217c478bd9Sstevel@tonic-gate 		bad_arg("New password entry too long");
16227c478bd9Sstevel@tonic-gate 	}
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate /* Check for the size of the whole passwd entry */
16267c478bd9Sstevel@tonic-gate void
162749335bdeSbasabi ck_s_sz(struct spwd *ssp)
16287c478bd9Sstevel@tonic-gate {
16297c478bd9Sstevel@tonic-gate 	char ctp[128];
16307c478bd9Sstevel@tonic-gate 
16317c478bd9Sstevel@tonic-gate 	/* Ensure that the combined length of the individual */
16327c478bd9Sstevel@tonic-gate 	/* fields will fit in a shadow entry. The 1 accounts for the */
16337c478bd9Sstevel@tonic-gate 	/* newline and the 7 accounts for the colons (:'s) */
16347c478bd9Sstevel@tonic-gate 	if (((int)strlen(ssp->sp_namp) + 1 +
16357c478bd9Sstevel@tonic-gate 	    (int)strlen(ssp->sp_pwdp) +
16367c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", ssp->sp_lstchg) +
16377c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", ssp->sp_min) +
16387c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", ssp->sp_max) +
16397c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", ssp->sp_warn) +
16407c478bd9Sstevel@tonic-gate 	    sprintf(ctp, "%d", ssp->sp_inact) +
16411316014bSbasabi 	    sprintf(ctp, "%d", ssp->sp_expire) + 7) > (ENTRY_LENGTH - 1)) {
16427c478bd9Sstevel@tonic-gate 		rid_tmpf();
16437c478bd9Sstevel@tonic-gate 		bad_arg("New password entry too long");
16447c478bd9Sstevel@tonic-gate 	}
16457c478bd9Sstevel@tonic-gate }
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate /* Get rid of the temp files */
16487c478bd9Sstevel@tonic-gate void
164949335bdeSbasabi rid_tmpf(void)
16507c478bd9Sstevel@tonic-gate {
16517c478bd9Sstevel@tonic-gate 	(void) fclose(fp_ptemp);
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 	if (unlink(PASSTEMP)) {
16547c478bd9Sstevel@tonic-gate 		msg = "%s: warning: cannot unlink %s\n";
16557c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(msg), prognamp, PASSTEMP);
16567c478bd9Sstevel@tonic-gate 	}
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 	if (info_mask & BOTH_FILES) {
16597c478bd9Sstevel@tonic-gate 		(void) fclose(fp_stemp);
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 		if (unlink(SHADTEMP)) {
16627c478bd9Sstevel@tonic-gate 			msg = "%s: warning: cannot unlink %s\n";
16637c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(msg), prognamp,
16647c478bd9Sstevel@tonic-gate 			    SHADTEMP);
16657c478bd9Sstevel@tonic-gate 		}
16667c478bd9Sstevel@tonic-gate 	}
16677c478bd9Sstevel@tonic-gate 
16687c478bd9Sstevel@tonic-gate 	if (info_mask & UATTR_FILE) {
16697c478bd9Sstevel@tonic-gate 		(void) fclose(fp_uatemp);
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 		if (unlink(USERATTR_TEMP)) {
16727c478bd9Sstevel@tonic-gate 			msg = "%s: warning: cannot unlink %s\n";
16737c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(msg), prognamp,
16747c478bd9Sstevel@tonic-gate 			    USERATTR_TEMP);
16757c478bd9Sstevel@tonic-gate 		}
16767c478bd9Sstevel@tonic-gate 	}
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate 
16797c478bd9Sstevel@tonic-gate void
16807c478bd9Sstevel@tonic-gate file_copy(FILE *spf, long NIS_pos)
16817c478bd9Sstevel@tonic-gate {
16827c478bd9Sstevel@tonic-gate 	int n;
16837c478bd9Sstevel@tonic-gate 	char buf[1024];
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	if (fseek(spf, NIS_pos, SEEK_SET) < 0) {
16867c478bd9Sstevel@tonic-gate 		rid_tmpf();
16877c478bd9Sstevel@tonic-gate 		file_error();
16887c478bd9Sstevel@tonic-gate 	}
16897c478bd9Sstevel@tonic-gate 	while ((n = fread(buf, sizeof (char), 1024, spf)) > 0) {
16907c478bd9Sstevel@tonic-gate 		if (fwrite(buf, sizeof (char), n, fp_stemp) != n) {
16917c478bd9Sstevel@tonic-gate 			rid_tmpf();
16927c478bd9Sstevel@tonic-gate 			file_error();
16937c478bd9Sstevel@tonic-gate 		}
16947c478bd9Sstevel@tonic-gate 	}
16957c478bd9Sstevel@tonic-gate }
1696