xref: /onnv-gate/usr/src/cmd/oamuser/user/userdefs.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate /*
27*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28*0Sstevel@tonic-gate  * Use is subject to license terms.
29*0Sstevel@tonic-gate  */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI" /* SVr4.0 1.4 */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate /*LINTLIBRARY*/
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include	<sys/types.h>
37*0Sstevel@tonic-gate #include	<stdio.h>
38*0Sstevel@tonic-gate #include	<string.h>
39*0Sstevel@tonic-gate #include	<userdefs.h>
40*0Sstevel@tonic-gate #include	<user_attr.h>
41*0Sstevel@tonic-gate #include	<limits.h>
42*0Sstevel@tonic-gate #include	<stdlib.h>
43*0Sstevel@tonic-gate #include	<stddef.h>
44*0Sstevel@tonic-gate #include	<time.h>
45*0Sstevel@tonic-gate #include	<unistd.h>
46*0Sstevel@tonic-gate #include	"userdisp.h"
47*0Sstevel@tonic-gate #include	"funcs.h"
48*0Sstevel@tonic-gate #include	"messages.h"
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate /* Print out a NL when the line gets too long */
51*0Sstevel@tonic-gate #define	PRINTNL()	\
52*0Sstevel@tonic-gate 	if (outcount > 40) { \
53*0Sstevel@tonic-gate 		outcount = 0; \
54*0Sstevel@tonic-gate 		(void) fprintf(fptr, "\n"); \
55*0Sstevel@tonic-gate 	}
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate #define	SKIPWS(ptr)	while (*ptr && *ptr == ' ' || *ptr == '\t') ptr++
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate static char *dup_to_nl(char *);
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate static struct userdefs defaults = {
62*0Sstevel@tonic-gate 	DEFRID, DEFGROUP, DEFGNAME, DEFPARENT, DEFSKL,
63*0Sstevel@tonic-gate 	DEFSHL, DEFINACT, DEFEXPIRE, DEFAUTH, DEFPROF,
64*0Sstevel@tonic-gate 	DEFROLE, DEFPROJ, DEFPROJNAME, DEFLIMPRIV,
65*0Sstevel@tonic-gate 	DEFDFLTPRIV, DEFLOCK_AFTER_RETRIES
66*0Sstevel@tonic-gate };
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #define	INT	0
69*0Sstevel@tonic-gate #define	STR	1
70*0Sstevel@tonic-gate #define	PROJID	2
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate #define	DEFOFF(field)		offsetof(struct userdefs, field)
73*0Sstevel@tonic-gate #define	FIELD(up, pe, type)	(*(type *)((char *)(up) + (pe)->off))
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate typedef struct parsent {
76*0Sstevel@tonic-gate 	const char *name;	/* deffoo= */
77*0Sstevel@tonic-gate 	const size_t nmsz;	/* length of def= string (excluding \0) */
78*0Sstevel@tonic-gate 	const int type;		/* type of entry */
79*0Sstevel@tonic-gate 	const ptrdiff_t off;	/* offset in userdefs structure */
80*0Sstevel@tonic-gate 	const char *uakey;	/* user_attr key, if defined */
81*0Sstevel@tonic-gate } parsent_t;
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate static const parsent_t tab[] = {
84*0Sstevel@tonic-gate 	{ GIDSTR,	sizeof (GIDSTR) - 1,	INT,	DEFOFF(defgroup) },
85*0Sstevel@tonic-gate 	{ GNAMSTR,	sizeof (GNAMSTR) - 1,	STR,	DEFOFF(defgname) },
86*0Sstevel@tonic-gate 	{ PARSTR,	sizeof (PARSTR) - 1,	STR,	DEFOFF(defparent) },
87*0Sstevel@tonic-gate 	{ SKLSTR,	sizeof (SKLSTR) - 1,	STR,	DEFOFF(defskel) },
88*0Sstevel@tonic-gate 	{ SHELLSTR,	sizeof (SHELLSTR) - 1,	STR,	DEFOFF(defshell) },
89*0Sstevel@tonic-gate 	{ INACTSTR,	sizeof (INACTSTR) - 1,	INT,	DEFOFF(definact) },
90*0Sstevel@tonic-gate 	{ EXPIRESTR,	sizeof (EXPIRESTR) - 1,	STR,	DEFOFF(defexpire) },
91*0Sstevel@tonic-gate 	{ AUTHSTR,	sizeof (AUTHSTR) - 1,	STR,	DEFOFF(defauth),
92*0Sstevel@tonic-gate 		USERATTR_AUTHS_KW },
93*0Sstevel@tonic-gate 	{ ROLESTR,	sizeof (ROLESTR) - 1,	STR,	DEFOFF(defrole),
94*0Sstevel@tonic-gate 		USERATTR_ROLES_KW },
95*0Sstevel@tonic-gate 	{ PROFSTR,	sizeof (PROFSTR) - 1,	STR,	DEFOFF(defprof),
96*0Sstevel@tonic-gate 		USERATTR_PROFILES_KW },
97*0Sstevel@tonic-gate 	{ PROJSTR,	sizeof (PROJSTR) - 1,	PROJID,	DEFOFF(defproj) },
98*0Sstevel@tonic-gate 	{ PROJNMSTR,	sizeof (PROJNMSTR) - 1,	STR,	DEFOFF(defprojname) },
99*0Sstevel@tonic-gate 	{ LIMPRSTR,	sizeof (LIMPRSTR) - 1,	STR,	DEFOFF(deflimpriv),
100*0Sstevel@tonic-gate 		USERATTR_LIMPRIV_KW },
101*0Sstevel@tonic-gate 	{ DFLTPRSTR,	sizeof (DFLTPRSTR) - 1,	STR,	DEFOFF(defdfltpriv),
102*0Sstevel@tonic-gate 		USERATTR_DFLTPRIV_KW },
103*0Sstevel@tonic-gate 	{ LOCK_AFTER_RETRIESSTR,	sizeof (LOCK_AFTER_RETRIESSTR) - 1,
104*0Sstevel@tonic-gate 		STR,	DEFOFF(deflock_after_retries),
105*0Sstevel@tonic-gate 		USERATTR_LOCK_AFTER_RETRIES_KW },
106*0Sstevel@tonic-gate };
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate #define	NDEF	(sizeof (tab) / sizeof (parsent_t))
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate FILE *defptr;		/* default file - fptr */
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate static const parsent_t *
113*0Sstevel@tonic-gate scan(char **start_p)
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate 	static int ind = NDEF - 1;
116*0Sstevel@tonic-gate 	char *cur_p = *start_p;
117*0Sstevel@tonic-gate 	int lastind = ind;
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	if (!*cur_p || *cur_p == '\n' || *cur_p == '#')
120*0Sstevel@tonic-gate 		return (NULL);
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	/*
123*0Sstevel@tonic-gate 	 * The magic in this loop is remembering the last index when
124*0Sstevel@tonic-gate 	 * reentering the function; the entries above are also used to
125*0Sstevel@tonic-gate 	 * order the output to the default file.
126*0Sstevel@tonic-gate 	 */
127*0Sstevel@tonic-gate 	do {
128*0Sstevel@tonic-gate 		ind++;
129*0Sstevel@tonic-gate 		ind %= NDEF;
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 		if (strncmp(cur_p, tab[ind].name, tab[ind].nmsz) == 0) {
132*0Sstevel@tonic-gate 			*start_p = cur_p + tab[ind].nmsz;
133*0Sstevel@tonic-gate 			return (&tab[ind]);
134*0Sstevel@tonic-gate 		}
135*0Sstevel@tonic-gate 	} while (ind != lastind);
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	return (NULL);
138*0Sstevel@tonic-gate }
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate /*
141*0Sstevel@tonic-gate  * getusrdef - access the user defaults file.  If it doesn't exist,
142*0Sstevel@tonic-gate  *		then returns default values of (values in userdefs.h):
143*0Sstevel@tonic-gate  *		defrid = 100
144*0Sstevel@tonic-gate  *		defgroup = 1
145*0Sstevel@tonic-gate  *		defgname = other
146*0Sstevel@tonic-gate  *		defparent = /home
147*0Sstevel@tonic-gate  *		defskel	= /usr/sadm/skel
148*0Sstevel@tonic-gate  *		defshell = /bin/sh
149*0Sstevel@tonic-gate  *		definact = 0
150*0Sstevel@tonic-gate  *		defexpire = 0
151*0Sstevel@tonic-gate  *		defauth = 0
152*0Sstevel@tonic-gate  *		defprof = 0
153*0Sstevel@tonic-gate  *		defrole = 0
154*0Sstevel@tonic-gate  *
155*0Sstevel@tonic-gate  *	If getusrdef() is unable to access the defaults file, it
156*0Sstevel@tonic-gate  *	returns a NULL pointer.
157*0Sstevel@tonic-gate  *
158*0Sstevel@tonic-gate  * 	If user defaults file exists, then getusrdef uses values
159*0Sstevel@tonic-gate  *  in it to override the above values.
160*0Sstevel@tonic-gate  */
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate struct userdefs *
163*0Sstevel@tonic-gate getusrdef(char *usertype)
164*0Sstevel@tonic-gate {
165*0Sstevel@tonic-gate 	char instr[512], *ptr;
166*0Sstevel@tonic-gate 	const parsent_t *pe;
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	if (is_role(usertype)) {
169*0Sstevel@tonic-gate 		if ((defptr = fopen(DEFROLEFILE, "r")) == NULL) {
170*0Sstevel@tonic-gate 			defaults.defshell = DEFROLESHL;
171*0Sstevel@tonic-gate 			defaults.defprof = DEFROLEPROF;
172*0Sstevel@tonic-gate 			return (&defaults);
173*0Sstevel@tonic-gate 		}
174*0Sstevel@tonic-gate 	} else {
175*0Sstevel@tonic-gate 		if ((defptr = fopen(DEFFILE, "r")) == NULL)
176*0Sstevel@tonic-gate 			return (&defaults);
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	while (fgets(instr, sizeof (instr), defptr) != NULL) {
180*0Sstevel@tonic-gate 		ptr = instr;
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate 		SKIPWS(ptr);
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 		if (*ptr == '#')
185*0Sstevel@tonic-gate 			continue;
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 		pe = scan(&ptr);
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 		if (pe != NULL) {
190*0Sstevel@tonic-gate 			switch (pe->type) {
191*0Sstevel@tonic-gate 			case INT:
192*0Sstevel@tonic-gate 				FIELD(&defaults, pe, int) =
193*0Sstevel@tonic-gate 					(int)strtol(ptr, NULL, 10);
194*0Sstevel@tonic-gate 				break;
195*0Sstevel@tonic-gate 			case PROJID:
196*0Sstevel@tonic-gate 				FIELD(&defaults, pe, projid_t) =
197*0Sstevel@tonic-gate 					(projid_t)strtol(ptr, NULL, 10);
198*0Sstevel@tonic-gate 				break;
199*0Sstevel@tonic-gate 			case STR:
200*0Sstevel@tonic-gate 				FIELD(&defaults, pe, char *) = dup_to_nl(ptr);
201*0Sstevel@tonic-gate 				break;
202*0Sstevel@tonic-gate 			}
203*0Sstevel@tonic-gate 		}
204*0Sstevel@tonic-gate 	}
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 	(void) fclose(defptr);
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 	return (&defaults);
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate static char *
212*0Sstevel@tonic-gate dup_to_nl(char *from)
213*0Sstevel@tonic-gate {
214*0Sstevel@tonic-gate 	char *res = strdup(from);
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	char *p = strchr(res, '\n');
217*0Sstevel@tonic-gate 	if (p)
218*0Sstevel@tonic-gate 		*p = '\0';
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	return (res);
221*0Sstevel@tonic-gate }
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate void
224*0Sstevel@tonic-gate dispusrdef(fptr, flags, usertype)
225*0Sstevel@tonic-gate FILE *fptr;
226*0Sstevel@tonic-gate unsigned flags;
227*0Sstevel@tonic-gate char *usertype;
228*0Sstevel@tonic-gate {
229*0Sstevel@tonic-gate 	struct userdefs *deflts = getusrdef(usertype);
230*0Sstevel@tonic-gate 	register outcount = 0;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	/* Print out values */
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	if (flags & D_GROUP) {
235*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "group=%s,%ld  ",
236*0Sstevel@tonic-gate 			deflts->defgname, deflts->defgroup);
237*0Sstevel@tonic-gate 		PRINTNL();
238*0Sstevel@tonic-gate 	}
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 	if (flags & D_PROJ) {
241*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "project=%s,%ld  ",
242*0Sstevel@tonic-gate 		    deflts->defprojname, deflts->defproj);
243*0Sstevel@tonic-gate 		PRINTNL();
244*0Sstevel@tonic-gate 	}
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	if (flags & D_BASEDIR) {
247*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "basedir=%s  ", deflts->defparent);
248*0Sstevel@tonic-gate 		PRINTNL();
249*0Sstevel@tonic-gate 	}
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	if (flags & D_RID) {
252*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "rid=%ld  ", deflts->defrid);
253*0Sstevel@tonic-gate 		PRINTNL();
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	if (flags & D_SKEL) {
257*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "skel=%s  ", deflts->defskel);
258*0Sstevel@tonic-gate 		PRINTNL();
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	if (flags & D_SHELL) {
262*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "shell=%s  ", deflts->defshell);
263*0Sstevel@tonic-gate 		PRINTNL();
264*0Sstevel@tonic-gate 	}
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	if (flags & D_INACT) {
267*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "inactive=%d  ", deflts->definact);
268*0Sstevel@tonic-gate 		PRINTNL();
269*0Sstevel@tonic-gate 	}
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	if (flags & D_EXPIRE) {
272*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "expire=%s  ", deflts->defexpire);
273*0Sstevel@tonic-gate 		PRINTNL();
274*0Sstevel@tonic-gate 	}
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 	if (flags & D_AUTH) {
277*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "auths=%s  ", deflts->defauth);
278*0Sstevel@tonic-gate 		PRINTNL();
279*0Sstevel@tonic-gate 	}
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	if (flags & D_PROF) {
282*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "profiles=%s  ", deflts->defprof);
283*0Sstevel@tonic-gate 		PRINTNL();
284*0Sstevel@tonic-gate 	}
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 	if ((flags & D_ROLE) &&
287*0Sstevel@tonic-gate 	    (!is_role(usertype))) {
288*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "roles=%s  ", deflts->defrole);
289*0Sstevel@tonic-gate 		PRINTNL();
290*0Sstevel@tonic-gate 	}
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate 	if (flags & D_LPRIV) {
293*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "limitpriv=%s  ",
294*0Sstevel@tonic-gate 			deflts->deflimpriv);
295*0Sstevel@tonic-gate 		PRINTNL();
296*0Sstevel@tonic-gate 	}
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	if (flags & D_DPRIV) {
299*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "defaultpriv=%s  ",
300*0Sstevel@tonic-gate 			deflts->defdfltpriv);
301*0Sstevel@tonic-gate 		PRINTNL();
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	if (flags & D_LOCK) {
305*0Sstevel@tonic-gate 		outcount += fprintf(fptr, "lock_after_retries=%s  ",
306*0Sstevel@tonic-gate 		    deflts->deflock_after_retries);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	if (outcount > 0)
310*0Sstevel@tonic-gate 		(void) fprintf(fptr, "\n");
311*0Sstevel@tonic-gate }
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate /*
314*0Sstevel@tonic-gate  * putusrdef -
315*0Sstevel@tonic-gate  * 	changes default values in defadduser file
316*0Sstevel@tonic-gate  */
317*0Sstevel@tonic-gate int
318*0Sstevel@tonic-gate putusrdef(struct userdefs *defs, char *usertype)
319*0Sstevel@tonic-gate {
320*0Sstevel@tonic-gate 	time_t timeval;		/* time value from time */
321*0Sstevel@tonic-gate 	int i;
322*0Sstevel@tonic-gate 	ptrdiff_t skip;
323*0Sstevel@tonic-gate 	char *hdr;
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	/*
326*0Sstevel@tonic-gate 	 * file format is:
327*0Sstevel@tonic-gate 	 * #<tab>Default values for adduser.  Changed mm/dd/yy hh:mm:ss.
328*0Sstevel@tonic-gate 	 * defgroup=m	(m=default group id)
329*0Sstevel@tonic-gate 	 * defgname=str1	(str1=default group name)
330*0Sstevel@tonic-gate 	 * defparent=str2	(str2=default base directory)
331*0Sstevel@tonic-gate 	 * definactive=x	(x=default inactive)
332*0Sstevel@tonic-gate 	 * defexpire=y		(y=default expire)
333*0Sstevel@tonic-gate 	 * defproj=z		(z=numeric project id)
334*0Sstevel@tonic-gate 	 * defprojname=str3	(str3=default project name)
335*0Sstevel@tonic-gate 	 * ... etc ...
336*0Sstevel@tonic-gate 	 */
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	if (is_role(usertype)) {
339*0Sstevel@tonic-gate 		if ((defptr = fopen(DEFROLEFILE, "w")) == NULL) {
340*0Sstevel@tonic-gate 			errmsg(M_FAILED);
341*0Sstevel@tonic-gate 			return (EX_UPDATE);
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate 	} else {
344*0Sstevel@tonic-gate 		if ((defptr = fopen(DEFFILE, "w")) == NULL) {
345*0Sstevel@tonic-gate 			errmsg(M_FAILED);
346*0Sstevel@tonic-gate 			return (EX_UPDATE);
347*0Sstevel@tonic-gate 		}
348*0Sstevel@tonic-gate 	}
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 	if (lockf(fileno(defptr), F_LOCK, 0) != 0) {
351*0Sstevel@tonic-gate 		/* print error if can't lock whole of DEFFILE */
352*0Sstevel@tonic-gate 		errmsg(M_UPDATE, "created");
353*0Sstevel@tonic-gate 		return (EX_UPDATE);
354*0Sstevel@tonic-gate 	}
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	if (is_role(usertype)) {
357*0Sstevel@tonic-gate 		/* If it's a role, we must skip the defrole field */
358*0Sstevel@tonic-gate 		skip = offsetof(struct userdefs, defrole);
359*0Sstevel@tonic-gate 		hdr = FHEADER_ROLE;
360*0Sstevel@tonic-gate 	} else {
361*0Sstevel@tonic-gate 		skip = -1;
362*0Sstevel@tonic-gate 		hdr = FHEADER;
363*0Sstevel@tonic-gate 	}
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	/* get time */
366*0Sstevel@tonic-gate 	timeval = time(NULL);
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	/* write it to file */
369*0Sstevel@tonic-gate 	if (fprintf(defptr, "%s%s\n", hdr, ctime(&timeval)) <= 0) {
370*0Sstevel@tonic-gate 		errmsg(M_UPDATE, "created");
371*0Sstevel@tonic-gate 		return (EX_UPDATE);
372*0Sstevel@tonic-gate 	}
373*0Sstevel@tonic-gate 
374*0Sstevel@tonic-gate 	for (i = 0; i < NDEF; i++) {
375*0Sstevel@tonic-gate 		int res = 0;
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 		if (tab[i].off == skip)
378*0Sstevel@tonic-gate 			continue;
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 		switch (tab[i].type) {
381*0Sstevel@tonic-gate 		case INT:
382*0Sstevel@tonic-gate 			res = fprintf(defptr, "%s%d\n", tab[i].name,
383*0Sstevel@tonic-gate 					FIELD(defs, &tab[i], int));
384*0Sstevel@tonic-gate 			break;
385*0Sstevel@tonic-gate 		case STR:
386*0Sstevel@tonic-gate 			res = fprintf(defptr, "%s%s\n", tab[i].name,
387*0Sstevel@tonic-gate 					FIELD(defs, &tab[i], char *));
388*0Sstevel@tonic-gate 			break;
389*0Sstevel@tonic-gate 		case PROJID:
390*0Sstevel@tonic-gate 			res = fprintf(defptr, "%s%d\n", tab[i].name,
391*0Sstevel@tonic-gate 					(int)FIELD(defs, &tab[i], projid_t));
392*0Sstevel@tonic-gate 			break;
393*0Sstevel@tonic-gate 		}
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 		if (res <= 0) {
396*0Sstevel@tonic-gate 			errmsg(M_UPDATE, "created");
397*0Sstevel@tonic-gate 			return (EX_UPDATE);
398*0Sstevel@tonic-gate 		}
399*0Sstevel@tonic-gate 	}
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 	(void) lockf(fileno(defptr), F_ULOCK, 0);
402*0Sstevel@tonic-gate 	(void) fclose(defptr);
403*0Sstevel@tonic-gate 
404*0Sstevel@tonic-gate 	return (EX_SUCCESS);
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate /* Export command line keys to defaults for useradd -D */
408*0Sstevel@tonic-gate void
409*0Sstevel@tonic-gate update_def(struct userdefs *ud)
410*0Sstevel@tonic-gate {
411*0Sstevel@tonic-gate 	int i;
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	for (i = 0; i < NDEF; i++) {
414*0Sstevel@tonic-gate 		char *val;
415*0Sstevel@tonic-gate 		if (tab[i].uakey != NULL &&
416*0Sstevel@tonic-gate 		    (val = getsetdefval(tab[i].uakey, NULL)) != NULL)
417*0Sstevel@tonic-gate 			FIELD(ud, &tab[i], char *) = val;
418*0Sstevel@tonic-gate 	}
419*0Sstevel@tonic-gate }
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate /* Import default keys for ordinary useradd */
422*0Sstevel@tonic-gate void
423*0Sstevel@tonic-gate import_def(struct userdefs *ud)
424*0Sstevel@tonic-gate {
425*0Sstevel@tonic-gate 	int i;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 	for (i = 0; i < NDEF; i++) {
428*0Sstevel@tonic-gate 		if (tab[i].uakey != NULL && tab[i].type == STR) {
429*0Sstevel@tonic-gate 			char *val = FIELD(ud, &tab[i], char *);
430*0Sstevel@tonic-gate 			if (val == getsetdefval(tab[i].uakey, val))
431*0Sstevel@tonic-gate 				nkeys ++;
432*0Sstevel@tonic-gate 		}
433*0Sstevel@tonic-gate 	}
434*0Sstevel@tonic-gate }
435