xref: /titanic_53/usr/src/cmd/oamuser/user/usermod.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
37*7c478bd9Sstevel@tonic-gate #include <stdio.h>
38*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
39*7c478bd9Sstevel@tonic-gate #include <ctype.h>
40*7c478bd9Sstevel@tonic-gate #include <limits.h>
41*7c478bd9Sstevel@tonic-gate #include <string.h>
42*7c478bd9Sstevel@tonic-gate #include <userdefs.h>
43*7c478bd9Sstevel@tonic-gate #include <user_attr.h>
44*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
45*7c478bd9Sstevel@tonic-gate #include <errno.h>
46*7c478bd9Sstevel@tonic-gate #include <project.h>
47*7c478bd9Sstevel@tonic-gate #include "users.h"
48*7c478bd9Sstevel@tonic-gate #include "messages.h"
49*7c478bd9Sstevel@tonic-gate #include "funcs.h"
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate /*
52*7c478bd9Sstevel@tonic-gate  *  usermod [-u uid [-o] | -g group | -G group [[,group]...] | -d dir [-m]
53*7c478bd9Sstevel@tonic-gate  *		| -s shell | -c comment | -l new_logname]
54*7c478bd9Sstevel@tonic-gate  *		| -f inactive | -e expire ]
55*7c478bd9Sstevel@tonic-gate  *		[ -A authorization [, authorization ...]]
56*7c478bd9Sstevel@tonic-gate  *		[ -P profile [, profile ...]]
57*7c478bd9Sstevel@tonic-gate  *		[ -R role [, role ...]]
58*7c478bd9Sstevel@tonic-gate  *		[ -K key=value ]
59*7c478bd9Sstevel@tonic-gate  *		[ -p project [, project]] login
60*7c478bd9Sstevel@tonic-gate  *
61*7c478bd9Sstevel@tonic-gate  *	This command adds new user logins to the system.  Arguments are:
62*7c478bd9Sstevel@tonic-gate  *
63*7c478bd9Sstevel@tonic-gate  *	uid - an integer less than MAXUID
64*7c478bd9Sstevel@tonic-gate  *	group - an existing group's integer ID or char string name
65*7c478bd9Sstevel@tonic-gate  *	dir - a directory
66*7c478bd9Sstevel@tonic-gate  *	shell - a program to be used as a shell
67*7c478bd9Sstevel@tonic-gate  *	comment - any text string
68*7c478bd9Sstevel@tonic-gate  *	skel_dir - a directory
69*7c478bd9Sstevel@tonic-gate  *	base_dir - a directory
70*7c478bd9Sstevel@tonic-gate  *	rid - an integer less than 2**16 (USHORT)
71*7c478bd9Sstevel@tonic-gate  *	login - a string of printable chars except colon (:)
72*7c478bd9Sstevel@tonic-gate  *	inactive - number of days a login maybe inactive before it is locked
73*7c478bd9Sstevel@tonic-gate  *	expire - date when a login is no longer valid
74*7c478bd9Sstevel@tonic-gate  *	authorization - One or more comma separated authorizations defined
75*7c478bd9Sstevel@tonic-gate  *			in auth_attr(4).
76*7c478bd9Sstevel@tonic-gate  *	profile - One or more comma separated execution profiles defined
77*7c478bd9Sstevel@tonic-gate  *		  in prof_attr(4)
78*7c478bd9Sstevel@tonic-gate  *	role - One or more comma-separated role names defined in user_attr(4)
79*7c478bd9Sstevel@tonic-gate  *	key=value - One or more -K options each specifying a valid user_attr(4)
80*7c478bd9Sstevel@tonic-gate  *		attribute.
81*7c478bd9Sstevel@tonic-gate  *
82*7c478bd9Sstevel@tonic-gate  */
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate extern int **valid_lgroup(), isbusy();
85*7c478bd9Sstevel@tonic-gate extern int valid_uid(), check_perm(), create_home(), move_dir();
86*7c478bd9Sstevel@tonic-gate extern int valid_expire(), edit_group(), call_passmgmt();
87*7c478bd9Sstevel@tonic-gate extern projid_t **valid_lproject();
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate static uid_t uid;		/* new uid */
90*7c478bd9Sstevel@tonic-gate static gid_t gid;			/* gid of new login */
91*7c478bd9Sstevel@tonic-gate static char *new_logname = NULL;	/* new login name with -l option */
92*7c478bd9Sstevel@tonic-gate static char *uidstr = NULL;		/* uid from command line */
93*7c478bd9Sstevel@tonic-gate static char *group = NULL;		/* group from command line */
94*7c478bd9Sstevel@tonic-gate static char *grps = NULL;		/* multi groups from command line */
95*7c478bd9Sstevel@tonic-gate static char *dir = NULL;		/* home dir from command line */
96*7c478bd9Sstevel@tonic-gate static char *shell = NULL;		/* shell from command line */
97*7c478bd9Sstevel@tonic-gate static char *comment = NULL;		/* comment from command line */
98*7c478bd9Sstevel@tonic-gate static char *logname = NULL;		/* login name to add */
99*7c478bd9Sstevel@tonic-gate static char *inactstr = NULL;		/* inactive from command line */
100*7c478bd9Sstevel@tonic-gate static char *expire = NULL;		/* expiration date from command line */
101*7c478bd9Sstevel@tonic-gate static char *projects = NULL;		/* project ids from command line */
102*7c478bd9Sstevel@tonic-gate static char *usertype;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate char *cmdname;
105*7c478bd9Sstevel@tonic-gate static char gidstring[32], uidstring[32];
106*7c478bd9Sstevel@tonic-gate char inactstring[10];
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate char *
109*7c478bd9Sstevel@tonic-gate strcpmalloc(str)
110*7c478bd9Sstevel@tonic-gate char *str;
111*7c478bd9Sstevel@tonic-gate {
112*7c478bd9Sstevel@tonic-gate 	if (str == NULL)
113*7c478bd9Sstevel@tonic-gate 		return (NULL);
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	return (strdup(str));
116*7c478bd9Sstevel@tonic-gate }
117*7c478bd9Sstevel@tonic-gate struct passwd *
118*7c478bd9Sstevel@tonic-gate passwd_cpmalloc(opw)
119*7c478bd9Sstevel@tonic-gate struct passwd *opw;
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate 	struct passwd *npw;
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	if (opw == NULL)
124*7c478bd9Sstevel@tonic-gate 		return (NULL);
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	npw = malloc(sizeof (struct passwd));
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	npw->pw_name = strcpmalloc(opw->pw_name);
130*7c478bd9Sstevel@tonic-gate 	npw->pw_passwd = strcpmalloc(opw->pw_passwd);
131*7c478bd9Sstevel@tonic-gate 	npw->pw_uid = opw->pw_uid;
132*7c478bd9Sstevel@tonic-gate 	npw->pw_gid = opw->pw_gid;
133*7c478bd9Sstevel@tonic-gate 	npw->pw_age = strcpmalloc(opw->pw_age);
134*7c478bd9Sstevel@tonic-gate 	npw->pw_comment = strcpmalloc(opw->pw_comment);
135*7c478bd9Sstevel@tonic-gate 	npw->pw_gecos  = strcpmalloc(opw->pw_gecos);
136*7c478bd9Sstevel@tonic-gate 	npw->pw_dir = strcpmalloc(opw->pw_dir);
137*7c478bd9Sstevel@tonic-gate 	npw->pw_shell = strcpmalloc(opw->pw_shell);
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	return (npw);
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate int
143*7c478bd9Sstevel@tonic-gate main(argc, argv)
144*7c478bd9Sstevel@tonic-gate int argc;
145*7c478bd9Sstevel@tonic-gate char **argv;
146*7c478bd9Sstevel@tonic-gate {
147*7c478bd9Sstevel@tonic-gate 	int ch, ret = EX_SUCCESS, call_pass = 0, oflag = 0;
148*7c478bd9Sstevel@tonic-gate 	int tries, mflag = 0, inact, **gidlist, flag = 0;
149*7c478bd9Sstevel@tonic-gate 	boolean_t fail_if_busy = B_FALSE;
150*7c478bd9Sstevel@tonic-gate 	char *ptr;
151*7c478bd9Sstevel@tonic-gate 	struct passwd *pstruct;		/* password struct for login */
152*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
153*7c478bd9Sstevel@tonic-gate 	struct group *g_ptr;	/* validated group from -g */
154*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;		/* status buffer for stat */
155*7c478bd9Sstevel@tonic-gate #ifndef att
156*7c478bd9Sstevel@tonic-gate 	FILE *pwf;		/* fille ptr for opened passwd file */
157*7c478bd9Sstevel@tonic-gate #endif
158*7c478bd9Sstevel@tonic-gate 	int warning;
159*7c478bd9Sstevel@tonic-gate 	projid_t **projlist;
160*7c478bd9Sstevel@tonic-gate 	char **nargv;			/* arguments for execvp of passmgmt */
161*7c478bd9Sstevel@tonic-gate 	int argindex;			/* argument index into nargv */
162*7c478bd9Sstevel@tonic-gate 	userattr_t *ua;
163*7c478bd9Sstevel@tonic-gate 	char *val;
164*7c478bd9Sstevel@tonic-gate 	int isrole;			/* current account is role */
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	cmdname = argv[0];
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) {
169*7c478bd9Sstevel@tonic-gate 		errmsg(M_PERM_DENIED);
170*7c478bd9Sstevel@tonic-gate 		exit(EX_NO_PERM);
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	opterr = 0;			/* no print errors from getopt */
174*7c478bd9Sstevel@tonic-gate 	/* get user type based on the program name */
175*7c478bd9Sstevel@tonic-gate 	usertype = getusertype(argv[0]);
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	while ((ch = getopt(argc, argv,
178*7c478bd9Sstevel@tonic-gate 				"c:d:e:f:G:g:l:mop:s:u:A:P:R:K:")) != EOF)
179*7c478bd9Sstevel@tonic-gate 		switch (ch) {
180*7c478bd9Sstevel@tonic-gate 		case 'c':
181*7c478bd9Sstevel@tonic-gate 			comment = optarg;
182*7c478bd9Sstevel@tonic-gate 			flag++;
183*7c478bd9Sstevel@tonic-gate 			break;
184*7c478bd9Sstevel@tonic-gate 		case 'd':
185*7c478bd9Sstevel@tonic-gate 			dir = optarg;
186*7c478bd9Sstevel@tonic-gate 			fail_if_busy = B_TRUE;
187*7c478bd9Sstevel@tonic-gate 			flag++;
188*7c478bd9Sstevel@tonic-gate 			break;
189*7c478bd9Sstevel@tonic-gate 		case 'e':
190*7c478bd9Sstevel@tonic-gate 			expire = optarg;
191*7c478bd9Sstevel@tonic-gate 			flag++;
192*7c478bd9Sstevel@tonic-gate 			break;
193*7c478bd9Sstevel@tonic-gate 		case 'f':
194*7c478bd9Sstevel@tonic-gate 			inactstr = optarg;
195*7c478bd9Sstevel@tonic-gate 			flag++;
196*7c478bd9Sstevel@tonic-gate 			break;
197*7c478bd9Sstevel@tonic-gate 		case 'G':
198*7c478bd9Sstevel@tonic-gate 			grps = optarg;
199*7c478bd9Sstevel@tonic-gate 			flag++;
200*7c478bd9Sstevel@tonic-gate 			break;
201*7c478bd9Sstevel@tonic-gate 		case 'g':
202*7c478bd9Sstevel@tonic-gate 			group = optarg;
203*7c478bd9Sstevel@tonic-gate 			fail_if_busy = B_TRUE;
204*7c478bd9Sstevel@tonic-gate 			flag++;
205*7c478bd9Sstevel@tonic-gate 			break;
206*7c478bd9Sstevel@tonic-gate 		case 'l':
207*7c478bd9Sstevel@tonic-gate 			new_logname = optarg;
208*7c478bd9Sstevel@tonic-gate 			fail_if_busy = B_TRUE;
209*7c478bd9Sstevel@tonic-gate 			flag++;
210*7c478bd9Sstevel@tonic-gate 			break;
211*7c478bd9Sstevel@tonic-gate 		case 'm':
212*7c478bd9Sstevel@tonic-gate 			mflag++;
213*7c478bd9Sstevel@tonic-gate 			flag++;
214*7c478bd9Sstevel@tonic-gate 			fail_if_busy = B_TRUE;
215*7c478bd9Sstevel@tonic-gate 			break;
216*7c478bd9Sstevel@tonic-gate 		case 'o':
217*7c478bd9Sstevel@tonic-gate 			oflag++;
218*7c478bd9Sstevel@tonic-gate 			flag++;
219*7c478bd9Sstevel@tonic-gate 			fail_if_busy = B_TRUE;
220*7c478bd9Sstevel@tonic-gate 			break;
221*7c478bd9Sstevel@tonic-gate 		case 'p':
222*7c478bd9Sstevel@tonic-gate 			projects = optarg;
223*7c478bd9Sstevel@tonic-gate 			flag++;
224*7c478bd9Sstevel@tonic-gate 			break;
225*7c478bd9Sstevel@tonic-gate 		case 's':
226*7c478bd9Sstevel@tonic-gate 			shell = optarg;
227*7c478bd9Sstevel@tonic-gate 			flag++;
228*7c478bd9Sstevel@tonic-gate 			break;
229*7c478bd9Sstevel@tonic-gate 		case 'u':
230*7c478bd9Sstevel@tonic-gate 			uidstr = optarg;
231*7c478bd9Sstevel@tonic-gate 			flag++;
232*7c478bd9Sstevel@tonic-gate 			fail_if_busy = B_TRUE;
233*7c478bd9Sstevel@tonic-gate 			break;
234*7c478bd9Sstevel@tonic-gate 		case 'A':
235*7c478bd9Sstevel@tonic-gate 			change_key(USERATTR_AUTHS_KW, optarg);
236*7c478bd9Sstevel@tonic-gate 			flag++;
237*7c478bd9Sstevel@tonic-gate 			break;
238*7c478bd9Sstevel@tonic-gate 		case 'P':
239*7c478bd9Sstevel@tonic-gate 			change_key(USERATTR_PROFILES_KW, optarg);
240*7c478bd9Sstevel@tonic-gate 			flag++;
241*7c478bd9Sstevel@tonic-gate 			break;
242*7c478bd9Sstevel@tonic-gate 		case 'R':
243*7c478bd9Sstevel@tonic-gate 			change_key(USERATTR_ROLES_KW, optarg);
244*7c478bd9Sstevel@tonic-gate 			flag++;
245*7c478bd9Sstevel@tonic-gate 			break;
246*7c478bd9Sstevel@tonic-gate 		case 'K':
247*7c478bd9Sstevel@tonic-gate 			change_key(NULL, optarg);
248*7c478bd9Sstevel@tonic-gate 			flag++;
249*7c478bd9Sstevel@tonic-gate 			break;
250*7c478bd9Sstevel@tonic-gate 		default:
251*7c478bd9Sstevel@tonic-gate 		case '?':
252*7c478bd9Sstevel@tonic-gate 			if (is_role(usertype))
253*7c478bd9Sstevel@tonic-gate 				errmsg(M_MRUSAGE);
254*7c478bd9Sstevel@tonic-gate 			else
255*7c478bd9Sstevel@tonic-gate 				errmsg(M_MUSAGE);
256*7c478bd9Sstevel@tonic-gate 			exit(EX_SYNTAX);
257*7c478bd9Sstevel@tonic-gate 		}
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	if (optind != argc - 1 || flag == 0) {
260*7c478bd9Sstevel@tonic-gate 		if (is_role(usertype))
261*7c478bd9Sstevel@tonic-gate 			errmsg(M_MRUSAGE);
262*7c478bd9Sstevel@tonic-gate 		else
263*7c478bd9Sstevel@tonic-gate 			errmsg(M_MUSAGE);
264*7c478bd9Sstevel@tonic-gate 		exit(EX_SYNTAX);
265*7c478bd9Sstevel@tonic-gate 	}
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	if ((!uidstr && oflag) || (mflag && !dir)) {
268*7c478bd9Sstevel@tonic-gate 		if (is_role(usertype))
269*7c478bd9Sstevel@tonic-gate 			errmsg(M_MRUSAGE);
270*7c478bd9Sstevel@tonic-gate 		else
271*7c478bd9Sstevel@tonic-gate 			errmsg(M_MUSAGE);
272*7c478bd9Sstevel@tonic-gate 		exit(EX_SYNTAX);
273*7c478bd9Sstevel@tonic-gate 	}
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	logname = argv[optind];
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	/* Determine whether the account is a role or not */
278*7c478bd9Sstevel@tonic-gate 	if ((ua = getusernam(logname)) == NULL ||
279*7c478bd9Sstevel@tonic-gate 	    (val = kva_match(ua->attr, USERATTR_TYPE_KW)) == NULL ||
280*7c478bd9Sstevel@tonic-gate 	    strcmp(val, USERATTR_TYPE_NONADMIN_KW) != 0)
281*7c478bd9Sstevel@tonic-gate 		isrole = 0;
282*7c478bd9Sstevel@tonic-gate 	else
283*7c478bd9Sstevel@tonic-gate 		isrole = 1;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	/* Verify that rolemod is used for roles and usermod for users */
286*7c478bd9Sstevel@tonic-gate 	if (isrole != is_role(usertype)) {
287*7c478bd9Sstevel@tonic-gate 		if (isrole)
288*7c478bd9Sstevel@tonic-gate 			errmsg(M_ISROLE);
289*7c478bd9Sstevel@tonic-gate 		else
290*7c478bd9Sstevel@tonic-gate 			errmsg(M_ISUSER);
291*7c478bd9Sstevel@tonic-gate 		exit(EX_SYNTAX);
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	/* Set the usertype key; defaults to the commandline  */
295*7c478bd9Sstevel@tonic-gate 	usertype = getsetdefval(USERATTR_TYPE_KW, usertype);
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	if (is_role(usertype)) {
298*7c478bd9Sstevel@tonic-gate 		/* Roles can't have roles */
299*7c478bd9Sstevel@tonic-gate 		if (getsetdefval(USERATTR_ROLES_KW, NULL) != NULL) {
300*7c478bd9Sstevel@tonic-gate 			errmsg(M_MRUSAGE);
301*7c478bd9Sstevel@tonic-gate 			exit(EX_SYNTAX);
302*7c478bd9Sstevel@tonic-gate 		}
303*7c478bd9Sstevel@tonic-gate 		/* If it was an ordinary user, delete its roles */
304*7c478bd9Sstevel@tonic-gate 		if (!isrole)
305*7c478bd9Sstevel@tonic-gate 			change_key(USERATTR_ROLES_KW, "");
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate #ifdef att
309*7c478bd9Sstevel@tonic-gate 	pw = getpwnam(logname);
310*7c478bd9Sstevel@tonic-gate #else
311*7c478bd9Sstevel@tonic-gate 	/*
312*7c478bd9Sstevel@tonic-gate 	 * Do this with fgetpwent to make sure we are only looking on local
313*7c478bd9Sstevel@tonic-gate 	 * system (since passmgmt only works on local system).
314*7c478bd9Sstevel@tonic-gate 	 */
315*7c478bd9Sstevel@tonic-gate 	if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
316*7c478bd9Sstevel@tonic-gate 		errmsg(M_OOPS, "open", "/etc/passwd");
317*7c478bd9Sstevel@tonic-gate 		exit(EX_FAILURE);
318*7c478bd9Sstevel@tonic-gate 	}
319*7c478bd9Sstevel@tonic-gate 	while ((pw = fgetpwent(pwf)) != NULL)
320*7c478bd9Sstevel@tonic-gate 		if (strcmp(pw->pw_name, logname) == 0)
321*7c478bd9Sstevel@tonic-gate 			break;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	fclose(pwf);
324*7c478bd9Sstevel@tonic-gate #endif
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	if (pw == NULL) {
327*7c478bd9Sstevel@tonic-gate 		char		pwdb[NSS_BUFLEN_PASSWD];
328*7c478bd9Sstevel@tonic-gate 		struct passwd	pwd;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 		if (getpwnam_r(logname, &pwd, pwdb, sizeof (pwdb)) == NULL) {
331*7c478bd9Sstevel@tonic-gate 			/* This user does not exist. */
332*7c478bd9Sstevel@tonic-gate 			errmsg(M_EXIST, logname);
333*7c478bd9Sstevel@tonic-gate 			exit(EX_NAME_NOT_EXIST);
334*7c478bd9Sstevel@tonic-gate 		} else {
335*7c478bd9Sstevel@tonic-gate 			/* This user exists in non-local name service. */
336*7c478bd9Sstevel@tonic-gate 			errmsg(M_NONLOCAL, logname);
337*7c478bd9Sstevel@tonic-gate 			exit(EX_NOT_LOCAL);
338*7c478bd9Sstevel@tonic-gate 		}
339*7c478bd9Sstevel@tonic-gate 	}
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	pstruct = passwd_cpmalloc(pw);
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	/*
344*7c478bd9Sstevel@tonic-gate 	 * We can't modify a logged in user if any of the following
345*7c478bd9Sstevel@tonic-gate 	 * are being changed:
346*7c478bd9Sstevel@tonic-gate 	 * uid (-u & -o), group (-g), home dir (-m), loginname (-l).
347*7c478bd9Sstevel@tonic-gate 	 * If none of those are specified it is okay to go ahead
348*7c478bd9Sstevel@tonic-gate 	 * some types of changes only take effect on next login, some
349*7c478bd9Sstevel@tonic-gate 	 * like authorisations and profiles take effect instantly.
350*7c478bd9Sstevel@tonic-gate 	 * One might think that -K type=role should require that the
351*7c478bd9Sstevel@tonic-gate 	 * user not be logged in, however this would make it very
352*7c478bd9Sstevel@tonic-gate 	 * difficult to make the root account a role using this command.
353*7c478bd9Sstevel@tonic-gate 	 */
354*7c478bd9Sstevel@tonic-gate 	if (isbusy(logname)) {
355*7c478bd9Sstevel@tonic-gate 		if (fail_if_busy) {
356*7c478bd9Sstevel@tonic-gate 			errmsg(M_BUSY, logname, "change");
357*7c478bd9Sstevel@tonic-gate 			exit(EX_BUSY);
358*7c478bd9Sstevel@tonic-gate 		}
359*7c478bd9Sstevel@tonic-gate 		warningmsg(WARN_LOGGED_IN, logname);
360*7c478bd9Sstevel@tonic-gate 	}
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	if (new_logname && strcmp(new_logname, logname)) {
363*7c478bd9Sstevel@tonic-gate 		switch (valid_login(new_logname, (struct passwd **)NULL,
364*7c478bd9Sstevel@tonic-gate 			&warning)) {
365*7c478bd9Sstevel@tonic-gate 		case INVALID:
366*7c478bd9Sstevel@tonic-gate 			errmsg(M_INVALID, new_logname, "login name");
367*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
368*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 		case NOTUNIQUE:
371*7c478bd9Sstevel@tonic-gate 			errmsg(M_USED, new_logname);
372*7c478bd9Sstevel@tonic-gate 			exit(EX_NAME_EXISTS);
373*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
374*7c478bd9Sstevel@tonic-gate 		default:
375*7c478bd9Sstevel@tonic-gate 			call_pass = 1;
376*7c478bd9Sstevel@tonic-gate 			break;
377*7c478bd9Sstevel@tonic-gate 		}
378*7c478bd9Sstevel@tonic-gate 		if (warning)
379*7c478bd9Sstevel@tonic-gate 			warningmsg(warning, logname);
380*7c478bd9Sstevel@tonic-gate 	}
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	if (uidstr) {
383*7c478bd9Sstevel@tonic-gate 		/* convert uidstr to integer */
384*7c478bd9Sstevel@tonic-gate 		errno = 0;
385*7c478bd9Sstevel@tonic-gate 		uid = (uid_t)strtol(uidstr, &ptr, (int)10);
386*7c478bd9Sstevel@tonic-gate 		if (*ptr || errno == ERANGE) {
387*7c478bd9Sstevel@tonic-gate 			errmsg(M_INVALID, uidstr, "user id");
388*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
389*7c478bd9Sstevel@tonic-gate 		}
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 		if (uid != pstruct->pw_uid) {
392*7c478bd9Sstevel@tonic-gate 			switch (valid_uid(uid, NULL)) {
393*7c478bd9Sstevel@tonic-gate 			case NOTUNIQUE:
394*7c478bd9Sstevel@tonic-gate 				if (!oflag) {
395*7c478bd9Sstevel@tonic-gate 					/* override not specified */
396*7c478bd9Sstevel@tonic-gate 					errmsg(M_UID_USED, uid);
397*7c478bd9Sstevel@tonic-gate 					exit(EX_ID_EXISTS);
398*7c478bd9Sstevel@tonic-gate 				}
399*7c478bd9Sstevel@tonic-gate 				break;
400*7c478bd9Sstevel@tonic-gate 			case RESERVED:
401*7c478bd9Sstevel@tonic-gate 				errmsg(M_RESERVED, uid);
402*7c478bd9Sstevel@tonic-gate 				break;
403*7c478bd9Sstevel@tonic-gate 			case TOOBIG:
404*7c478bd9Sstevel@tonic-gate 				errmsg(M_TOOBIG, "uid", uid);
405*7c478bd9Sstevel@tonic-gate 				exit(EX_BADARG);
406*7c478bd9Sstevel@tonic-gate 				break;
407*7c478bd9Sstevel@tonic-gate 			}
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 			call_pass = 1;
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 		} else {
412*7c478bd9Sstevel@tonic-gate 			/* uid's the same, so don't change anything */
413*7c478bd9Sstevel@tonic-gate 			uidstr = NULL;
414*7c478bd9Sstevel@tonic-gate 			oflag = 0;
415*7c478bd9Sstevel@tonic-gate 		}
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	} else uid = pstruct->pw_uid;
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	if (group) {
420*7c478bd9Sstevel@tonic-gate 		switch (valid_group(group, &g_ptr, &warning)) {
421*7c478bd9Sstevel@tonic-gate 		case INVALID:
422*7c478bd9Sstevel@tonic-gate 			errmsg(M_INVALID, group, "group id");
423*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
424*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
425*7c478bd9Sstevel@tonic-gate 		case TOOBIG:
426*7c478bd9Sstevel@tonic-gate 			errmsg(M_TOOBIG, "gid", group);
427*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
428*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
429*7c478bd9Sstevel@tonic-gate 		case UNIQUE:
430*7c478bd9Sstevel@tonic-gate 			errmsg(M_GRP_NOTUSED, group);
431*7c478bd9Sstevel@tonic-gate 			exit(EX_NAME_NOT_EXIST);
432*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
433*7c478bd9Sstevel@tonic-gate 		case RESERVED:
434*7c478bd9Sstevel@tonic-gate 			gid = (gid_t)strtol(group, &ptr, (int)10);
435*7c478bd9Sstevel@tonic-gate 			errmsg(M_RESERVED_GID, gid);
436*7c478bd9Sstevel@tonic-gate 			break;
437*7c478bd9Sstevel@tonic-gate 		}
438*7c478bd9Sstevel@tonic-gate 		if (warning)
439*7c478bd9Sstevel@tonic-gate 			warningmsg(warning, group);
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 		if (g_ptr != NULL)
442*7c478bd9Sstevel@tonic-gate 			gid = g_ptr->gr_gid;
443*7c478bd9Sstevel@tonic-gate 		else
444*7c478bd9Sstevel@tonic-gate 			gid = pstruct->pw_gid;
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 		/* call passmgmt if gid is different, else ignore group */
447*7c478bd9Sstevel@tonic-gate 		if (gid != pstruct->pw_gid)
448*7c478bd9Sstevel@tonic-gate 			call_pass = 1;
449*7c478bd9Sstevel@tonic-gate 		else group = NULL;
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	} else gid = pstruct->pw_gid;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	if (grps && *grps) {
454*7c478bd9Sstevel@tonic-gate 		if (!(gidlist = valid_lgroup(grps, gid)))
455*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
456*7c478bd9Sstevel@tonic-gate 	} else
457*7c478bd9Sstevel@tonic-gate 		gidlist = (int **)0;
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 	if (projects && *projects) {
460*7c478bd9Sstevel@tonic-gate 		if (! (projlist = valid_lproject(projects)))
461*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
462*7c478bd9Sstevel@tonic-gate 	} else
463*7c478bd9Sstevel@tonic-gate 		projlist = (projid_t **)0;
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 	if (dir) {
466*7c478bd9Sstevel@tonic-gate 		if (REL_PATH(dir)) {
467*7c478bd9Sstevel@tonic-gate 			errmsg(M_RELPATH, dir);
468*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
469*7c478bd9Sstevel@tonic-gate 		}
470*7c478bd9Sstevel@tonic-gate 		if (strcmp(pstruct->pw_dir, dir) == 0) {
471*7c478bd9Sstevel@tonic-gate 			/* home directory is the same so ignore dflag & mflag */
472*7c478bd9Sstevel@tonic-gate 			dir = NULL;
473*7c478bd9Sstevel@tonic-gate 			mflag = 0;
474*7c478bd9Sstevel@tonic-gate 		} else call_pass = 1;
475*7c478bd9Sstevel@tonic-gate 	}
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	if (mflag) {
478*7c478bd9Sstevel@tonic-gate 		if (stat(dir, &statbuf) == 0) {
479*7c478bd9Sstevel@tonic-gate 			/* Home directory exists */
480*7c478bd9Sstevel@tonic-gate 			if (check_perm(statbuf, pstruct->pw_uid,
481*7c478bd9Sstevel@tonic-gate 			    pstruct->pw_gid, S_IWOTH|S_IXOTH) != 0) {
482*7c478bd9Sstevel@tonic-gate 				errmsg(M_NO_PERM, logname, dir);
483*7c478bd9Sstevel@tonic-gate 				exit(EX_NO_PERM);
484*7c478bd9Sstevel@tonic-gate 			}
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 		} else ret = create_home(dir, NULL, uid, gid);
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 		if (ret == EX_SUCCESS)
489*7c478bd9Sstevel@tonic-gate 			ret = move_dir(pstruct->pw_dir, dir, logname);
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 		if (ret != EX_SUCCESS)
492*7c478bd9Sstevel@tonic-gate 			exit(ret);
493*7c478bd9Sstevel@tonic-gate 	}
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	if (shell) {
496*7c478bd9Sstevel@tonic-gate 		if (REL_PATH(shell)) {
497*7c478bd9Sstevel@tonic-gate 			errmsg(M_RELPATH, shell);
498*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
499*7c478bd9Sstevel@tonic-gate 		}
500*7c478bd9Sstevel@tonic-gate 		if (strcmp(pstruct->pw_shell, shell) == 0) {
501*7c478bd9Sstevel@tonic-gate 			/* ignore s option if shell is not different */
502*7c478bd9Sstevel@tonic-gate 			shell = NULL;
503*7c478bd9Sstevel@tonic-gate 		} else {
504*7c478bd9Sstevel@tonic-gate 			if (stat(shell, &statbuf) < 0 ||
505*7c478bd9Sstevel@tonic-gate 			    (statbuf.st_mode & S_IFMT) != S_IFREG ||
506*7c478bd9Sstevel@tonic-gate 			    (statbuf.st_mode & 0555) != 0555) {
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 				errmsg(M_INVALID, shell, "shell");
509*7c478bd9Sstevel@tonic-gate 				exit(EX_BADARG);
510*7c478bd9Sstevel@tonic-gate 			}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 			call_pass = 1;
513*7c478bd9Sstevel@tonic-gate 		}
514*7c478bd9Sstevel@tonic-gate 	}
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	if (comment)
517*7c478bd9Sstevel@tonic-gate 		/* ignore comment if comment is not changed */
518*7c478bd9Sstevel@tonic-gate 		if (strcmp(pstruct->pw_comment, comment))
519*7c478bd9Sstevel@tonic-gate 			call_pass = 1;
520*7c478bd9Sstevel@tonic-gate 		else
521*7c478bd9Sstevel@tonic-gate 			comment = NULL;
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	/* inactive string is a positive integer */
524*7c478bd9Sstevel@tonic-gate 	if (inactstr) {
525*7c478bd9Sstevel@tonic-gate 		/* convert inactstr to integer */
526*7c478bd9Sstevel@tonic-gate 		inact = (int)strtol(inactstr, &ptr, 10);
527*7c478bd9Sstevel@tonic-gate 		if (*ptr || inact < 0) {
528*7c478bd9Sstevel@tonic-gate 			errmsg(M_INVALID, inactstr, "inactivity period");
529*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
530*7c478bd9Sstevel@tonic-gate 		}
531*7c478bd9Sstevel@tonic-gate 		call_pass = 1;
532*7c478bd9Sstevel@tonic-gate 	}
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	/* expiration string is a date, newer than today */
535*7c478bd9Sstevel@tonic-gate 	if (expire) {
536*7c478bd9Sstevel@tonic-gate 		if (*expire &&
537*7c478bd9Sstevel@tonic-gate 		    valid_expire(expire, (time_t *)0) == INVALID) {
538*7c478bd9Sstevel@tonic-gate 			errmsg(M_INVALID, expire, "expiration date");
539*7c478bd9Sstevel@tonic-gate 			exit(EX_BADARG);
540*7c478bd9Sstevel@tonic-gate 		}
541*7c478bd9Sstevel@tonic-gate 		call_pass = 1;
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	if (nkeys > 0)
545*7c478bd9Sstevel@tonic-gate 		call_pass = 1;
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	/* that's it for validations - now do the work */
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	if (grps) {
550*7c478bd9Sstevel@tonic-gate 		/* redefine login's supplentary group memberships */
551*7c478bd9Sstevel@tonic-gate 		ret = edit_group(logname, new_logname, gidlist, 1);
552*7c478bd9Sstevel@tonic-gate 		if (ret != EX_SUCCESS) {
553*7c478bd9Sstevel@tonic-gate 			errmsg(M_UPDATE, "modified");
554*7c478bd9Sstevel@tonic-gate 			exit(ret);
555*7c478bd9Sstevel@tonic-gate 		}
556*7c478bd9Sstevel@tonic-gate 	}
557*7c478bd9Sstevel@tonic-gate 	if (projects) {
558*7c478bd9Sstevel@tonic-gate 		ret = edit_project(logname, (char *)NULL, projlist, 0);
559*7c478bd9Sstevel@tonic-gate 		if (ret != EX_SUCCESS) {
560*7c478bd9Sstevel@tonic-gate 			errmsg(M_UPDATE, "modified");
561*7c478bd9Sstevel@tonic-gate 			exit(ret);
562*7c478bd9Sstevel@tonic-gate 		}
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	if (!call_pass) exit(ret);
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	/* only get to here if need to call passmgmt */
569*7c478bd9Sstevel@tonic-gate 	/* set up arguments to  passmgmt in nargv array */
570*7c478bd9Sstevel@tonic-gate 	nargv = malloc((30 + nkeys * 2) * sizeof (char *));
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	argindex = 0;
573*7c478bd9Sstevel@tonic-gate 	nargv[argindex++] = "passmgmt";
574*7c478bd9Sstevel@tonic-gate 	nargv[argindex++] = "-m";	/* modify */
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	if (comment) {	/* comment */
577*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-c";
578*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = comment;
579*7c478bd9Sstevel@tonic-gate 	}
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	if (dir) {
582*7c478bd9Sstevel@tonic-gate 		/* flags for home directory */
583*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-h";
584*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = dir;
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	if (group) {
588*7c478bd9Sstevel@tonic-gate 		/* set gid flag */
589*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-g";
590*7c478bd9Sstevel@tonic-gate 		(void) sprintf(gidstring, "%ld", gid);
591*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = gidstring;
592*7c478bd9Sstevel@tonic-gate 	}
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	if (shell) { 	/* shell */
595*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-s";
596*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = shell;
597*7c478bd9Sstevel@tonic-gate 	}
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 	if (inactstr) {
600*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-f";
601*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = inactstr;
602*7c478bd9Sstevel@tonic-gate 	}
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 	if (expire) {
605*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-e";
606*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = expire;
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	if (uidstr) {	/* set uid flag */
610*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-u";
611*7c478bd9Sstevel@tonic-gate 		(void) sprintf(uidstring, "%ld", uid);
612*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = uidstring;
613*7c478bd9Sstevel@tonic-gate 	}
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	if (oflag) nargv[argindex++] = "-o";
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	if (new_logname) {	/* redefine login name */
618*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = "-l";
619*7c478bd9Sstevel@tonic-gate 		nargv[argindex++] = new_logname;
620*7c478bd9Sstevel@tonic-gate 	}
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	if (nkeys > 0)
623*7c478bd9Sstevel@tonic-gate 		addkey_args(nargv, &argindex);
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	/* finally - login name */
626*7c478bd9Sstevel@tonic-gate 	nargv[argindex++] = logname;
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 	/* set the last to null */
629*7c478bd9Sstevel@tonic-gate 	nargv[argindex++] = NULL;
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	/* now call passmgmt */
632*7c478bd9Sstevel@tonic-gate 	ret = PEX_FAILED;
633*7c478bd9Sstevel@tonic-gate 	for (tries = 3; ret != PEX_SUCCESS && tries--; ) {
634*7c478bd9Sstevel@tonic-gate 		switch (ret = call_passmgmt(nargv)) {
635*7c478bd9Sstevel@tonic-gate 		case PEX_SUCCESS:
636*7c478bd9Sstevel@tonic-gate 		case PEX_BUSY:
637*7c478bd9Sstevel@tonic-gate 			break;
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate 		case PEX_HOSED_FILES:
640*7c478bd9Sstevel@tonic-gate 			errmsg(M_HOSED_FILES);
641*7c478bd9Sstevel@tonic-gate 			exit(EX_INCONSISTENT);
642*7c478bd9Sstevel@tonic-gate 			break;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 		case PEX_SYNTAX:
645*7c478bd9Sstevel@tonic-gate 		case PEX_BADARG:
646*7c478bd9Sstevel@tonic-gate 			/* should NEVER occur that passmgmt usage is wrong */
647*7c478bd9Sstevel@tonic-gate 			if (is_role(usertype))
648*7c478bd9Sstevel@tonic-gate 				errmsg(M_MRUSAGE);
649*7c478bd9Sstevel@tonic-gate 			else
650*7c478bd9Sstevel@tonic-gate 				errmsg(M_MUSAGE);
651*7c478bd9Sstevel@tonic-gate 			exit(EX_SYNTAX);
652*7c478bd9Sstevel@tonic-gate 			break;
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 		case PEX_BADUID:
655*7c478bd9Sstevel@tonic-gate 			/* uid in use - shouldn't happen print message anyway */
656*7c478bd9Sstevel@tonic-gate 			errmsg(M_UID_USED, uid);
657*7c478bd9Sstevel@tonic-gate 			exit(EX_ID_EXISTS);
658*7c478bd9Sstevel@tonic-gate 			break;
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 		case PEX_BADNAME:
661*7c478bd9Sstevel@tonic-gate 			/* invalid loname */
662*7c478bd9Sstevel@tonic-gate 			errmsg(M_USED, logname);
663*7c478bd9Sstevel@tonic-gate 			exit(EX_NAME_EXISTS);
664*7c478bd9Sstevel@tonic-gate 			break;
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate 		default:
667*7c478bd9Sstevel@tonic-gate 			errmsg(M_UPDATE, "modified");
668*7c478bd9Sstevel@tonic-gate 			exit(ret);
669*7c478bd9Sstevel@tonic-gate 			break;
670*7c478bd9Sstevel@tonic-gate 		}
671*7c478bd9Sstevel@tonic-gate 	}
672*7c478bd9Sstevel@tonic-gate 	if (tries == 0) {
673*7c478bd9Sstevel@tonic-gate 		errmsg(M_UPDATE, "modified");
674*7c478bd9Sstevel@tonic-gate 	}
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	exit(ret);
677*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
678*7c478bd9Sstevel@tonic-gate }
679