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