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