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 1999-2003 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include "mt.h"
30*7c478bd9Sstevel@tonic-gate #include <stdio.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
33*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
34*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h>
35*7c478bd9Sstevel@tonic-gate #include <string.h>
36*7c478bd9Sstevel@tonic-gate #include <strings.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
38*7c478bd9Sstevel@tonic-gate #include <thread.h>
39*7c478bd9Sstevel@tonic-gate #include <synch.h>
40*7c478bd9Sstevel@tonic-gate #include <nsswitch.h>
41*7c478bd9Sstevel@tonic-gate #include <prof_attr.h>
42*7c478bd9Sstevel@tonic-gate #include <exec_attr.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /* externs from libc */
45*7c478bd9Sstevel@tonic-gate extern void _nss_db_state_destr(struct nss_db_state *);
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate /* externs from parse.c */
48*7c478bd9Sstevel@tonic-gate extern char *_strtok_escape(char *, char *, char **);
49*7c478bd9Sstevel@tonic-gate extern char *_strdup_null(char *);
50*7c478bd9Sstevel@tonic-gate /* extern from getprofattr.c */
51*7c478bd9Sstevel@tonic-gate extern int str2profattr(const char *, int, void *, char *, int);
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate char *_exec_wild_id(char *, const char *);
54*7c478bd9Sstevel@tonic-gate execstr_t *_dup_execstr(execstr_t *);
55*7c478bd9Sstevel@tonic-gate void _free_execstr(execstr_t *);
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static char *_nsw_search_path = NULL;
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate  * Unsynchronized, but it affects only efficiency, not correctness
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(exec_root);
64*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context);
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate void
67*7c478bd9Sstevel@tonic-gate _nss_initf_execattr(nss_db_params_t *p)
68*7c478bd9Sstevel@tonic-gate {
69*7c478bd9Sstevel@tonic-gate 	trace1(TR__nss_initf_execattr, 0);
70*7c478bd9Sstevel@tonic-gate 	p->name = NSS_DBNAM_EXECATTR;
71*7c478bd9Sstevel@tonic-gate 	p->config_name    = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */
72*7c478bd9Sstevel@tonic-gate 	trace1(TR__nss_initf_execattr, 1);
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate void
76*7c478bd9Sstevel@tonic-gate _nsw_initf_execattr(nss_db_params_t *p)
77*7c478bd9Sstevel@tonic-gate {
78*7c478bd9Sstevel@tonic-gate 	trace1(TR__nss_initf_execattr, 0);
79*7c478bd9Sstevel@tonic-gate 	p->name = NSS_DBNAM_EXECATTR;
80*7c478bd9Sstevel@tonic-gate 	p->flags |= NSS_USE_DEFAULT_CONFIG;
81*7c478bd9Sstevel@tonic-gate 	p->default_config = _nsw_search_path;
82*7c478bd9Sstevel@tonic-gate 	trace1(TR__nss_initf_execattr, 1);
83*7c478bd9Sstevel@tonic-gate }
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate void
86*7c478bd9Sstevel@tonic-gate _nsw_initf_profattr(nss_db_params_t *p)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 	trace1(TR__nss_initf_execattr, 0);
89*7c478bd9Sstevel@tonic-gate 	p->name = NSS_DBNAM_PROFATTR;
90*7c478bd9Sstevel@tonic-gate 	p->flags |= NSS_USE_DEFAULT_CONFIG;
91*7c478bd9Sstevel@tonic-gate 	p->default_config = _nsw_search_path;
92*7c478bd9Sstevel@tonic-gate 	trace1(TR__nss_initf_execattr, 1);
93*7c478bd9Sstevel@tonic-gate }
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate /*
96*7c478bd9Sstevel@tonic-gate  * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure
97*7c478bd9Sstevel@tonic-gate  * pointer passed in is a structure in the caller's space wherein the field
98*7c478bd9Sstevel@tonic-gate  * pointers would be set to areas in the buffer if need be. instring and buffer
99*7c478bd9Sstevel@tonic-gate  * should be separate areas.
100*7c478bd9Sstevel@tonic-gate  */
101*7c478bd9Sstevel@tonic-gate int
102*7c478bd9Sstevel@tonic-gate str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate 	char		*last = (char *)NULL;
105*7c478bd9Sstevel@tonic-gate 	char		*sep = KV_TOKEN_DELIMIT;
106*7c478bd9Sstevel@tonic-gate 	char		*empty = KV_EMPTY;
107*7c478bd9Sstevel@tonic-gate 	execstr_t	*exec = (execstr_t *)ent;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	if (exec == NULL) {
110*7c478bd9Sstevel@tonic-gate 		return (NSS_STR_PARSE_PARSE);
111*7c478bd9Sstevel@tonic-gate 	}
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	trace3(TR_str2execattr, 0, lenstr, buflen);
114*7c478bd9Sstevel@tonic-gate 	if ((instr >= buffer && (buffer + buflen) > instr) ||
115*7c478bd9Sstevel@tonic-gate 	    (buffer >= instr && (instr + lenstr) > buffer)) {
116*7c478bd9Sstevel@tonic-gate 		trace3(TR_str2execattr, 1, lenstr, buflen);
117*7c478bd9Sstevel@tonic-gate 		return (NSS_STR_PARSE_PARSE);
118*7c478bd9Sstevel@tonic-gate 	}
119*7c478bd9Sstevel@tonic-gate 	if (lenstr >= buflen) {
120*7c478bd9Sstevel@tonic-gate 		trace3(TR_str2execattr, 1, lenstr, buflen);
121*7c478bd9Sstevel@tonic-gate 		return (NSS_STR_PARSE_ERANGE);
122*7c478bd9Sstevel@tonic-gate 	}
123*7c478bd9Sstevel@tonic-gate 	strncpy(buffer, instr, buflen);
124*7c478bd9Sstevel@tonic-gate 	/*
125*7c478bd9Sstevel@tonic-gate 	 * Remove newline that nis (yp_match) puts at the
126*7c478bd9Sstevel@tonic-gate 	 * end of the entry it retrieves from the map.
127*7c478bd9Sstevel@tonic-gate 	 */
128*7c478bd9Sstevel@tonic-gate 	if (buffer[lenstr] == '\n') {
129*7c478bd9Sstevel@tonic-gate 		buffer[lenstr] = '\0';
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	exec->name = _strtok_escape(buffer, sep, &last);
133*7c478bd9Sstevel@tonic-gate 	exec->policy = _strtok_escape(NULL, sep, &last);
134*7c478bd9Sstevel@tonic-gate 	exec->type = _strtok_escape(NULL, sep, &last);
135*7c478bd9Sstevel@tonic-gate 	exec->res1 = _strtok_escape(NULL, sep, &last);
136*7c478bd9Sstevel@tonic-gate 	exec->res2 = _strtok_escape(NULL, sep, &last);
137*7c478bd9Sstevel@tonic-gate 	exec->id = _strtok_escape(NULL, sep, &last);
138*7c478bd9Sstevel@tonic-gate 	exec->attr = _strtok_escape(NULL, sep, &last);
139*7c478bd9Sstevel@tonic-gate 	exec->next = (execstr_t *)NULL;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	return (NSS_STR_PARSE_SUCCESS);
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate void
146*7c478bd9Sstevel@tonic-gate _setexecattr(void)
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate 	trace1(TR_setexecattr, 0);
149*7c478bd9Sstevel@tonic-gate 	nss_setent(&exec_root, _nss_initf_execattr, &context);
150*7c478bd9Sstevel@tonic-gate 	trace1(TR_setexecattr, 0);
151*7c478bd9Sstevel@tonic-gate }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate void
155*7c478bd9Sstevel@tonic-gate _endexecattr(void)
156*7c478bd9Sstevel@tonic-gate {
157*7c478bd9Sstevel@tonic-gate 	trace1(TR_endexecattr, 0);
158*7c478bd9Sstevel@tonic-gate 	nss_endent(&exec_root, _nss_initf_execattr, &context);
159*7c478bd9Sstevel@tonic-gate 	nss_delete(&exec_root);
160*7c478bd9Sstevel@tonic-gate 	trace1(TR_endexecattr, 0);
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate execstr_t *
165*7c478bd9Sstevel@tonic-gate _getexecattr(execstr_t *result, char *buffer, int buflen, int *errnop)
166*7c478bd9Sstevel@tonic-gate {
167*7c478bd9Sstevel@tonic-gate 	nss_status_t    res;
168*7c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t arg;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	trace2(TR_getexecattr, 0, buflen);
171*7c478bd9Sstevel@tonic-gate 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
172*7c478bd9Sstevel@tonic-gate 	res = nss_getent(&exec_root, _nss_initf_execattr, &context, &arg);
173*7c478bd9Sstevel@tonic-gate 	arg.status = res;
174*7c478bd9Sstevel@tonic-gate 	*errnop = arg.h_errno;
175*7c478bd9Sstevel@tonic-gate 	trace2(TR_getexecattr, 1, buflen);
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate execstr_t *
181*7c478bd9Sstevel@tonic-gate _getexecprof(char *name,
182*7c478bd9Sstevel@tonic-gate     char *type,
183*7c478bd9Sstevel@tonic-gate     char *id,
184*7c478bd9Sstevel@tonic-gate     int search_flag,
185*7c478bd9Sstevel@tonic-gate     execstr_t *result,
186*7c478bd9Sstevel@tonic-gate     char *buffer,
187*7c478bd9Sstevel@tonic-gate     int buflen,
188*7c478bd9Sstevel@tonic-gate     int *errnop)
189*7c478bd9Sstevel@tonic-gate {
190*7c478bd9Sstevel@tonic-gate 	int		getby_flag;
191*7c478bd9Sstevel@tonic-gate 	char		policy_buf[BUFSIZ];
192*7c478bd9Sstevel@tonic-gate 	const char	*empty = (const char *)NULL;
193*7c478bd9Sstevel@tonic-gate 	nss_status_t	res = NSS_NOTFOUND;
194*7c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t	arg;
195*7c478bd9Sstevel@tonic-gate 	_priv_execattr	_priv_exec;
196*7c478bd9Sstevel@tonic-gate 	static mutex_t	_nsw_exec_lock = DEFAULTMUTEX;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 	trace2(TR_getexecprof, 0, _buflen);
199*7c478bd9Sstevel@tonic-gate 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	_priv_exec.name = (name == NULL) ? empty : (const char *)name;
202*7c478bd9Sstevel@tonic-gate 	_priv_exec.type = (type == NULL) ? empty : (const char *)type;
203*7c478bd9Sstevel@tonic-gate 	_priv_exec.id = (id == NULL) ? empty : (const char *)id;
204*7c478bd9Sstevel@tonic-gate #ifdef SI_SECPOLICY
205*7c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1)
206*7c478bd9Sstevel@tonic-gate #endif	/* SI_SECPOLICY */
207*7c478bd9Sstevel@tonic-gate 	strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ);
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate retry_policy:
210*7c478bd9Sstevel@tonic-gate 	_priv_exec.policy = policy_buf;
211*7c478bd9Sstevel@tonic-gate 	_priv_exec.search_flag = search_flag;
212*7c478bd9Sstevel@tonic-gate 	_priv_exec.head_exec = (execstr_t *)NULL;
213*7c478bd9Sstevel@tonic-gate 	_priv_exec.prev_exec = (execstr_t *)NULL;
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate 	if ((name != NULL) && (id != NULL)) {
216*7c478bd9Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYNAMEID;
217*7c478bd9Sstevel@tonic-gate 	} else if (name != NULL) {
218*7c478bd9Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYNAME;
219*7c478bd9Sstevel@tonic-gate 	} else if (id != NULL) {
220*7c478bd9Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYID;
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	arg.key.attrp = &(_priv_exec);
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	switch (getby_flag) {
226*7c478bd9Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYID:
227*7c478bd9Sstevel@tonic-gate 		res = nss_search(&exec_root, _nss_initf_execattr, getby_flag,
228*7c478bd9Sstevel@tonic-gate 		    &arg);
229*7c478bd9Sstevel@tonic-gate 		break;
230*7c478bd9Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYNAMEID:
231*7c478bd9Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYNAME:
232*7c478bd9Sstevel@tonic-gate 		{
233*7c478bd9Sstevel@tonic-gate 			char			pbuf[NSS_BUFLEN_PROFATTR];
234*7c478bd9Sstevel@tonic-gate 			profstr_t		prof;
235*7c478bd9Sstevel@tonic-gate 			nss_status_t		pres;
236*7c478bd9Sstevel@tonic-gate 			nss_XbyY_args_t		parg;
237*7c478bd9Sstevel@tonic-gate 			enum __nsw_parse_err	pserr;
238*7c478bd9Sstevel@tonic-gate 			struct __nsw_lookup	*lookups = NULL;
239*7c478bd9Sstevel@tonic-gate 			struct __nsw_switchconfig *conf = NULL;
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 			if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr))
242*7c478bd9Sstevel@tonic-gate 				if ((lookups = conf->lookups) == NULL)
243*7c478bd9Sstevel@tonic-gate 					goto out;
244*7c478bd9Sstevel@tonic-gate 			NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR,
245*7c478bd9Sstevel@tonic-gate 			    str2profattr);
246*7c478bd9Sstevel@tonic-gate 			parg.key.name = name;
247*7c478bd9Sstevel@tonic-gate 			do {
248*7c478bd9Sstevel@tonic-gate 				/*
249*7c478bd9Sstevel@tonic-gate 				 * search the exec_attr entry only in the scope
250*7c478bd9Sstevel@tonic-gate 				 * that we find the profile in.
251*7c478bd9Sstevel@tonic-gate 				 * if conf = NULL, search in local files only,
252*7c478bd9Sstevel@tonic-gate 				 * as we were not able to read nsswitch.conf.
253*7c478bd9Sstevel@tonic-gate 				 */
254*7c478bd9Sstevel@tonic-gate 				DEFINE_NSS_DB_ROOT(prof_root);
255*7c478bd9Sstevel@tonic-gate 				if (mutex_lock(&_nsw_exec_lock) != 0)
256*7c478bd9Sstevel@tonic-gate 					goto out;
257*7c478bd9Sstevel@tonic-gate 				_nsw_search_path = (conf == NULL)
258*7c478bd9Sstevel@tonic-gate 				    ? NSS_FILES_ONLY
259*7c478bd9Sstevel@tonic-gate 				    : lookups->service_name;
260*7c478bd9Sstevel@tonic-gate 				pres = nss_search(&prof_root,
261*7c478bd9Sstevel@tonic-gate 				    _nsw_initf_profattr,
262*7c478bd9Sstevel@tonic-gate 				    NSS_DBOP_PROFATTR_BYNAME, &parg);
263*7c478bd9Sstevel@tonic-gate 				if (pres == NSS_SUCCESS) {
264*7c478bd9Sstevel@tonic-gate 					DEFINE_NSS_DB_ROOT(pexec_root);
265*7c478bd9Sstevel@tonic-gate 					res = nss_search(&pexec_root,
266*7c478bd9Sstevel@tonic-gate 					    _nsw_initf_execattr, getby_flag,
267*7c478bd9Sstevel@tonic-gate 					    &arg);
268*7c478bd9Sstevel@tonic-gate 					_nss_db_state_destr(pexec_root.s);
269*7c478bd9Sstevel@tonic-gate 				}
270*7c478bd9Sstevel@tonic-gate 				_nss_db_state_destr(prof_root.s);
271*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&_nsw_exec_lock);
272*7c478bd9Sstevel@tonic-gate 				if ((pres == NSS_SUCCESS) || (conf == NULL))
273*7c478bd9Sstevel@tonic-gate 					break;
274*7c478bd9Sstevel@tonic-gate 			} while (lookups && (lookups = lookups->next));
275*7c478bd9Sstevel@tonic-gate 		}
276*7c478bd9Sstevel@tonic-gate 		break;
277*7c478bd9Sstevel@tonic-gate 	default:
278*7c478bd9Sstevel@tonic-gate 		break;
279*7c478bd9Sstevel@tonic-gate 	}
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate out:
282*7c478bd9Sstevel@tonic-gate 	/*
283*7c478bd9Sstevel@tonic-gate 	 * If we can't find an entry for the current default policy
284*7c478bd9Sstevel@tonic-gate 	 * fall back to the old "suser" policy.  The nameservice is
285*7c478bd9Sstevel@tonic-gate 	 * shared between different OS releases.
286*7c478bd9Sstevel@tonic-gate 	 */
287*7c478bd9Sstevel@tonic-gate 	if (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0) {
288*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ);
289*7c478bd9Sstevel@tonic-gate 		goto retry_policy;
290*7c478bd9Sstevel@tonic-gate 	}
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	arg.status = res;
293*7c478bd9Sstevel@tonic-gate 	*errnop = res;
294*7c478bd9Sstevel@tonic-gate 	trace2(TR_getexecprof, 1, buflen);
295*7c478bd9Sstevel@tonic-gate 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate int
300*7c478bd9Sstevel@tonic-gate _doexeclist(nss_XbyY_args_t *argp)
301*7c478bd9Sstevel@tonic-gate {
302*7c478bd9Sstevel@tonic-gate 	int		status = 1;
303*7c478bd9Sstevel@tonic-gate 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
304*7c478bd9Sstevel@tonic-gate 	execstr_t	*exec = (execstr_t *)((argp->buf.result));
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	if (_priv_exec->head_exec == NULL) {
307*7c478bd9Sstevel@tonic-gate 		if (_priv_exec->head_exec = _dup_execstr(exec))
308*7c478bd9Sstevel@tonic-gate 			_priv_exec->prev_exec = _priv_exec->head_exec;
309*7c478bd9Sstevel@tonic-gate 		else
310*7c478bd9Sstevel@tonic-gate 			status = 0;
311*7c478bd9Sstevel@tonic-gate 	} else {
312*7c478bd9Sstevel@tonic-gate 		if (_priv_exec->prev_exec->next = _dup_execstr(exec))
313*7c478bd9Sstevel@tonic-gate 			_priv_exec->prev_exec = _priv_exec->prev_exec->next;
314*7c478bd9Sstevel@tonic-gate 		else
315*7c478bd9Sstevel@tonic-gate 			status = 0;
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 	memset(argp->buf.buffer, NULL, argp->buf.buflen);
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	return (status);
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate }
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate /*
325*7c478bd9Sstevel@tonic-gate  * Converts id to a wildcard string. e.g.:
326*7c478bd9Sstevel@tonic-gate  *   For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \*
327*7c478bd9Sstevel@tonic-gate  *   For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;*
328*7c478bd9Sstevel@tonic-gate  *
329*7c478bd9Sstevel@tonic-gate  * Returns NULL if id is already a wild-card.
330*7c478bd9Sstevel@tonic-gate  */
331*7c478bd9Sstevel@tonic-gate char *
332*7c478bd9Sstevel@tonic-gate _exec_wild_id(char *id, const char *type)
333*7c478bd9Sstevel@tonic-gate {
334*7c478bd9Sstevel@tonic-gate 	char	c_id = '/';
335*7c478bd9Sstevel@tonic-gate 	char	*pchar = NULL;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	if ((id == NULL) || (type == NULL))
338*7c478bd9Sstevel@tonic-gate 		return (NULL);
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 	if (strcmp(type, KV_ACTION) == 0) {
341*7c478bd9Sstevel@tonic-gate 		return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL :
342*7c478bd9Sstevel@tonic-gate 		    KV_ACTION_WILDCARD);
343*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(type, KV_COMMAND) == 0) {
344*7c478bd9Sstevel@tonic-gate 		if ((pchar = rindex(id, c_id)) == NULL)
345*7c478bd9Sstevel@tonic-gate 			/*
346*7c478bd9Sstevel@tonic-gate 			 * id = \*
347*7c478bd9Sstevel@tonic-gate 			 */
348*7c478bd9Sstevel@tonic-gate 			return (NULL);
349*7c478bd9Sstevel@tonic-gate 		else if (*(++pchar) == KV_WILDCHAR)
350*7c478bd9Sstevel@tonic-gate 			/*
351*7c478bd9Sstevel@tonic-gate 			 * id = /usr/ccs/bin/\*
352*7c478bd9Sstevel@tonic-gate 			 */
353*7c478bd9Sstevel@tonic-gate 			return (pchar);
354*7c478bd9Sstevel@tonic-gate 		/*
355*7c478bd9Sstevel@tonic-gate 		 * id = /usr/ccs/bin/what
356*7c478bd9Sstevel@tonic-gate 		 */
357*7c478bd9Sstevel@tonic-gate 		strcpy(pchar, KV_WILDCARD);
358*7c478bd9Sstevel@tonic-gate 		return (id);
359*7c478bd9Sstevel@tonic-gate 	}
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	return (NULL);
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate }
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate execstr_t *
367*7c478bd9Sstevel@tonic-gate _dup_execstr(execstr_t *old_exec)
368*7c478bd9Sstevel@tonic-gate {
369*7c478bd9Sstevel@tonic-gate 	execstr_t *new_exec = (execstr_t *)NULL;
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	if (old_exec == NULL) {
372*7c478bd9Sstevel@tonic-gate 		return ((execstr_t *)NULL);
373*7c478bd9Sstevel@tonic-gate 	}
374*7c478bd9Sstevel@tonic-gate 	if ((new_exec = (execstr_t *)malloc(sizeof (execstr_t))) != NULL) {
375*7c478bd9Sstevel@tonic-gate 		new_exec->name = _strdup_null(old_exec->name);
376*7c478bd9Sstevel@tonic-gate 		new_exec->type = _strdup_null(old_exec->type);
377*7c478bd9Sstevel@tonic-gate 		new_exec->policy = _strdup_null(old_exec->policy);
378*7c478bd9Sstevel@tonic-gate 		new_exec->res1 = _strdup_null(old_exec->res1);
379*7c478bd9Sstevel@tonic-gate 		new_exec->res2 = _strdup_null(old_exec->res2);
380*7c478bd9Sstevel@tonic-gate 		new_exec->id = _strdup_null(old_exec->id);
381*7c478bd9Sstevel@tonic-gate 		new_exec->attr = _strdup_null(old_exec->attr);
382*7c478bd9Sstevel@tonic-gate 		new_exec->next = old_exec->next;
383*7c478bd9Sstevel@tonic-gate 	}
384*7c478bd9Sstevel@tonic-gate 	return (new_exec);
385*7c478bd9Sstevel@tonic-gate }
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate void
388*7c478bd9Sstevel@tonic-gate _free_execstr(execstr_t *exec)
389*7c478bd9Sstevel@tonic-gate {
390*7c478bd9Sstevel@tonic-gate 	if (exec != NULL) {
391*7c478bd9Sstevel@tonic-gate 		free(exec->name);
392*7c478bd9Sstevel@tonic-gate 		free(exec->type);
393*7c478bd9Sstevel@tonic-gate 		free(exec->policy);
394*7c478bd9Sstevel@tonic-gate 		free(exec->res1);
395*7c478bd9Sstevel@tonic-gate 		free(exec->res2);
396*7c478bd9Sstevel@tonic-gate 		free(exec->id);
397*7c478bd9Sstevel@tonic-gate 		free(exec->attr);
398*7c478bd9Sstevel@tonic-gate 		_free_execstr(exec->next);
399*7c478bd9Sstevel@tonic-gate 		free(exec);
400*7c478bd9Sstevel@tonic-gate 	}
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate void
404*7c478bd9Sstevel@tonic-gate _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp)
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	if (res == NSS_SUCCESS) {
409*7c478bd9Sstevel@tonic-gate 		if (_priv_exec->head_exec != NULL) {
410*7c478bd9Sstevel@tonic-gate 			argp->buf.result = _priv_exec->head_exec;
411*7c478bd9Sstevel@tonic-gate 			argp->returnval = argp->buf.result;
412*7c478bd9Sstevel@tonic-gate 		}
413*7c478bd9Sstevel@tonic-gate 	} else {
414*7c478bd9Sstevel@tonic-gate 		if (_priv_exec->head_exec != NULL)
415*7c478bd9Sstevel@tonic-gate 			_free_execstr(_priv_exec->head_exec);
416*7c478bd9Sstevel@tonic-gate 		argp->returnval = NULL;
417*7c478bd9Sstevel@tonic-gate 	}
418*7c478bd9Sstevel@tonic-gate }
419