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
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * 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*01ef659dSJoep Vesseur  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include "mt.h"
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <strings.h>
337c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
347c478bd9Sstevel@tonic-gate #include <thread.h>
357c478bd9Sstevel@tonic-gate #include <synch.h>
367c478bd9Sstevel@tonic-gate #include <nsswitch.h>
377c478bd9Sstevel@tonic-gate #include <prof_attr.h>
387c478bd9Sstevel@tonic-gate #include <exec_attr.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /* externs from libc */
417c478bd9Sstevel@tonic-gate extern void _nss_db_state_destr(struct nss_db_state *);
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* externs from parse.c */
447c478bd9Sstevel@tonic-gate extern char *_strtok_escape(char *, char *, char **);
457c478bd9Sstevel@tonic-gate extern char *_strdup_null(char *);
467c478bd9Sstevel@tonic-gate /* extern from getprofattr.c */
477c478bd9Sstevel@tonic-gate extern int str2profattr(const char *, int, void *, char *, int);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate char *_exec_wild_id(char *, const char *);
507c478bd9Sstevel@tonic-gate execstr_t *_dup_execstr(execstr_t *);
517c478bd9Sstevel@tonic-gate void _free_execstr(execstr_t *);
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate static char *_nsw_search_path = NULL;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * Unsynchronized, but it affects only efficiency, not correctness
577c478bd9Sstevel@tonic-gate  */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(exec_root);
607c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate void
637c478bd9Sstevel@tonic-gate _nss_initf_execattr(nss_db_params_t *p)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 	p->name = NSS_DBNAM_EXECATTR;
667c478bd9Sstevel@tonic-gate 	p->config_name    = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate void
707c478bd9Sstevel@tonic-gate _nsw_initf_execattr(nss_db_params_t *p)
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	p->name = NSS_DBNAM_EXECATTR;
737c478bd9Sstevel@tonic-gate 	p->flags |= NSS_USE_DEFAULT_CONFIG;
747c478bd9Sstevel@tonic-gate 	p->default_config = _nsw_search_path;
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate void
787c478bd9Sstevel@tonic-gate _nsw_initf_profattr(nss_db_params_t *p)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate 	p->name = NSS_DBNAM_PROFATTR;
817c478bd9Sstevel@tonic-gate 	p->flags |= NSS_USE_DEFAULT_CONFIG;
827c478bd9Sstevel@tonic-gate 	p->default_config = _nsw_search_path;
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate  * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure
877c478bd9Sstevel@tonic-gate  * pointer passed in is a structure in the caller's space wherein the field
887c478bd9Sstevel@tonic-gate  * pointers would be set to areas in the buffer if need be. instring and buffer
897c478bd9Sstevel@tonic-gate  * should be separate areas.
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate int
927c478bd9Sstevel@tonic-gate str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
937c478bd9Sstevel@tonic-gate {
9461961e0fSrobinson 	char		*last = NULL;
957c478bd9Sstevel@tonic-gate 	char		*sep = KV_TOKEN_DELIMIT;
967c478bd9Sstevel@tonic-gate 	execstr_t	*exec = (execstr_t *)ent;
977c478bd9Sstevel@tonic-gate 
9861961e0fSrobinson 	if (lenstr >= buflen)
997c478bd9Sstevel@tonic-gate 		return (NSS_STR_PARSE_ERANGE);
100cb5caa98Sdjl 
101cb5caa98Sdjl 	if (instr != buffer)
102cb5caa98Sdjl 		(void) strncpy(buffer, instr, buflen);
103cb5caa98Sdjl 
1047c478bd9Sstevel@tonic-gate 	/*
1057c478bd9Sstevel@tonic-gate 	 * Remove newline that nis (yp_match) puts at the
1067c478bd9Sstevel@tonic-gate 	 * end of the entry it retrieves from the map.
1077c478bd9Sstevel@tonic-gate 	 */
1087c478bd9Sstevel@tonic-gate 	if (buffer[lenstr] == '\n') {
1097c478bd9Sstevel@tonic-gate 		buffer[lenstr] = '\0';
1107c478bd9Sstevel@tonic-gate 	}
1117c478bd9Sstevel@tonic-gate 
112cb5caa98Sdjl 	/* quick exit do not entry fill if not needed */
113cb5caa98Sdjl 	if (ent == (void *)NULL)
114cb5caa98Sdjl 		return (NSS_STR_PARSE_SUCCESS);
115cb5caa98Sdjl 
1167c478bd9Sstevel@tonic-gate 	exec->name = _strtok_escape(buffer, sep, &last);
1177c478bd9Sstevel@tonic-gate 	exec->policy = _strtok_escape(NULL, sep, &last);
1187c478bd9Sstevel@tonic-gate 	exec->type = _strtok_escape(NULL, sep, &last);
1197c478bd9Sstevel@tonic-gate 	exec->res1 = _strtok_escape(NULL, sep, &last);
1207c478bd9Sstevel@tonic-gate 	exec->res2 = _strtok_escape(NULL, sep, &last);
1217c478bd9Sstevel@tonic-gate 	exec->id = _strtok_escape(NULL, sep, &last);
1227c478bd9Sstevel@tonic-gate 	exec->attr = _strtok_escape(NULL, sep, &last);
12361961e0fSrobinson 	exec->next = NULL;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	return (NSS_STR_PARSE_SUCCESS);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate void
1307c478bd9Sstevel@tonic-gate _setexecattr(void)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	nss_setent(&exec_root, _nss_initf_execattr, &context);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate void
1377c478bd9Sstevel@tonic-gate _endexecattr(void)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	nss_endent(&exec_root, _nss_initf_execattr, &context);
1407c478bd9Sstevel@tonic-gate 	nss_delete(&exec_root);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate execstr_t *
1457c478bd9Sstevel@tonic-gate _getexecattr(execstr_t *result, char *buffer, int buflen, int *errnop)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 	nss_status_t    res;
1487c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t arg;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
1517c478bd9Sstevel@tonic-gate 	res = nss_getent(&exec_root, _nss_initf_execattr, &context, &arg);
1527c478bd9Sstevel@tonic-gate 	arg.status = res;
1537c478bd9Sstevel@tonic-gate 	*errnop = arg.h_errno;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate execstr_t *
1597c478bd9Sstevel@tonic-gate _getexecprof(char *name,
1607c478bd9Sstevel@tonic-gate     char *type,
1617c478bd9Sstevel@tonic-gate     char *id,
1627c478bd9Sstevel@tonic-gate     int search_flag,
1637c478bd9Sstevel@tonic-gate     execstr_t *result,
1647c478bd9Sstevel@tonic-gate     char *buffer,
1657c478bd9Sstevel@tonic-gate     int buflen,
1667c478bd9Sstevel@tonic-gate     int *errnop)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	int		getby_flag;
1697c478bd9Sstevel@tonic-gate 	char		policy_buf[BUFSIZ];
17061961e0fSrobinson 	const char	*empty = NULL;
1717c478bd9Sstevel@tonic-gate 	nss_status_t	res = NSS_NOTFOUND;
1727c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t	arg;
1737c478bd9Sstevel@tonic-gate 	_priv_execattr	_priv_exec;
1747c478bd9Sstevel@tonic-gate 	static mutex_t	_nsw_exec_lock = DEFAULTMUTEX;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	_priv_exec.name = (name == NULL) ? empty : (const char *)name;
1797c478bd9Sstevel@tonic-gate 	_priv_exec.type = (type == NULL) ? empty : (const char *)type;
1807c478bd9Sstevel@tonic-gate 	_priv_exec.id = (id == NULL) ? empty : (const char *)id;
1817c478bd9Sstevel@tonic-gate #ifdef SI_SECPOLICY
1827c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1)
1837c478bd9Sstevel@tonic-gate #endif	/* SI_SECPOLICY */
18461961e0fSrobinson 	(void) strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ);
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate retry_policy:
187*01ef659dSJoep Vesseur 	_priv_exec.policy = IS_SEARCH_ALL(search_flag) ? empty : policy_buf;
1887c478bd9Sstevel@tonic-gate 	_priv_exec.search_flag = search_flag;
18961961e0fSrobinson 	_priv_exec.head_exec = NULL;
19061961e0fSrobinson 	_priv_exec.prev_exec = NULL;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if ((name != NULL) && (id != NULL)) {
1937c478bd9Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYNAMEID;
1947c478bd9Sstevel@tonic-gate 	} else if (name != NULL) {
1957c478bd9Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYNAME;
1967c478bd9Sstevel@tonic-gate 	} else if (id != NULL) {
1977c478bd9Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYID;
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	arg.key.attrp = &(_priv_exec);
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	switch (getby_flag) {
2037c478bd9Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYID:
2047c478bd9Sstevel@tonic-gate 		res = nss_search(&exec_root, _nss_initf_execattr, getby_flag,
2057c478bd9Sstevel@tonic-gate 		    &arg);
2067c478bd9Sstevel@tonic-gate 		break;
2077c478bd9Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYNAMEID:
2087c478bd9Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYNAME:
2097c478bd9Sstevel@tonic-gate 		{
2107c478bd9Sstevel@tonic-gate 			char			pbuf[NSS_BUFLEN_PROFATTR];
2117c478bd9Sstevel@tonic-gate 			profstr_t		prof;
2127c478bd9Sstevel@tonic-gate 			nss_status_t		pres;
2137c478bd9Sstevel@tonic-gate 			nss_XbyY_args_t		parg;
2147c478bd9Sstevel@tonic-gate 			enum __nsw_parse_err	pserr;
2157c478bd9Sstevel@tonic-gate 			struct __nsw_lookup	*lookups = NULL;
2167c478bd9Sstevel@tonic-gate 			struct __nsw_switchconfig *conf = NULL;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 			if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr))
2197c478bd9Sstevel@tonic-gate 				if ((lookups = conf->lookups) == NULL)
2207c478bd9Sstevel@tonic-gate 					goto out;
2217c478bd9Sstevel@tonic-gate 			NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR,
2227c478bd9Sstevel@tonic-gate 			    str2profattr);
2237c478bd9Sstevel@tonic-gate 			parg.key.name = name;
2247c478bd9Sstevel@tonic-gate 			do {
2257c478bd9Sstevel@tonic-gate 				/*
2267c478bd9Sstevel@tonic-gate 				 * search the exec_attr entry only in the scope
2277c478bd9Sstevel@tonic-gate 				 * that we find the profile in.
2287c478bd9Sstevel@tonic-gate 				 * if conf = NULL, search in local files only,
2297c478bd9Sstevel@tonic-gate 				 * as we were not able to read nsswitch.conf.
2307c478bd9Sstevel@tonic-gate 				 */
2317c478bd9Sstevel@tonic-gate 				DEFINE_NSS_DB_ROOT(prof_root);
2327c478bd9Sstevel@tonic-gate 				if (mutex_lock(&_nsw_exec_lock) != 0)
2337c478bd9Sstevel@tonic-gate 					goto out;
2347c478bd9Sstevel@tonic-gate 				_nsw_search_path = (conf == NULL)
2357c478bd9Sstevel@tonic-gate 				    ? NSS_FILES_ONLY
2367c478bd9Sstevel@tonic-gate 				    : lookups->service_name;
2377c478bd9Sstevel@tonic-gate 				pres = nss_search(&prof_root,
2387c478bd9Sstevel@tonic-gate 				    _nsw_initf_profattr,
2397c478bd9Sstevel@tonic-gate 				    NSS_DBOP_PROFATTR_BYNAME, &parg);
2407c478bd9Sstevel@tonic-gate 				if (pres == NSS_SUCCESS) {
2417c478bd9Sstevel@tonic-gate 					DEFINE_NSS_DB_ROOT(pexec_root);
2427c478bd9Sstevel@tonic-gate 					res = nss_search(&pexec_root,
2437c478bd9Sstevel@tonic-gate 					    _nsw_initf_execattr, getby_flag,
2447c478bd9Sstevel@tonic-gate 					    &arg);
245cb5caa98Sdjl 					if (pexec_root.s != NULL)
246cb5caa98Sdjl 						_nss_db_state_destr(
247*01ef659dSJoep Vesseur 						    pexec_root.s);
2487c478bd9Sstevel@tonic-gate 				}
249cb5caa98Sdjl 				if (prof_root.s != NULL)
250cb5caa98Sdjl 					_nss_db_state_destr(prof_root.s);
2517c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&_nsw_exec_lock);
2527c478bd9Sstevel@tonic-gate 				if ((pres == NSS_SUCCESS) || (conf == NULL))
2537c478bd9Sstevel@tonic-gate 					break;
2547c478bd9Sstevel@tonic-gate 			} while (lookups && (lookups = lookups->next));
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 		break;
2577c478bd9Sstevel@tonic-gate 	default:
2587c478bd9Sstevel@tonic-gate 		break;
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate out:
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * If we can't find an entry for the current default policy
2647c478bd9Sstevel@tonic-gate 	 * fall back to the old "suser" policy.  The nameservice is
2657c478bd9Sstevel@tonic-gate 	 * shared between different OS releases.
2667c478bd9Sstevel@tonic-gate 	 */
267*01ef659dSJoep Vesseur 	if (!IS_SEARCH_ALL(search_flag) &&
268*01ef659dSJoep Vesseur 	    (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0)) {
2697c478bd9Sstevel@tonic-gate 		(void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ);
2707c478bd9Sstevel@tonic-gate 		goto retry_policy;
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	arg.status = res;
2747c478bd9Sstevel@tonic-gate 	*errnop = res;
2757c478bd9Sstevel@tonic-gate 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate int
2807c478bd9Sstevel@tonic-gate _doexeclist(nss_XbyY_args_t *argp)
2817c478bd9Sstevel@tonic-gate {
2827c478bd9Sstevel@tonic-gate 	int		status = 1;
2837c478bd9Sstevel@tonic-gate 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
2847c478bd9Sstevel@tonic-gate 	execstr_t	*exec = (execstr_t *)((argp->buf.result));
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	if (_priv_exec->head_exec == NULL) {
2877c478bd9Sstevel@tonic-gate 		if (_priv_exec->head_exec = _dup_execstr(exec))
2887c478bd9Sstevel@tonic-gate 			_priv_exec->prev_exec = _priv_exec->head_exec;
2897c478bd9Sstevel@tonic-gate 		else
2907c478bd9Sstevel@tonic-gate 			status = 0;
2917c478bd9Sstevel@tonic-gate 	} else {
2927c478bd9Sstevel@tonic-gate 		if (_priv_exec->prev_exec->next = _dup_execstr(exec))
2937c478bd9Sstevel@tonic-gate 			_priv_exec->prev_exec = _priv_exec->prev_exec->next;
2947c478bd9Sstevel@tonic-gate 		else
2957c478bd9Sstevel@tonic-gate 			status = 0;
2967c478bd9Sstevel@tonic-gate 	}
29761961e0fSrobinson 	(void) memset(argp->buf.buffer, NULL, argp->buf.buflen);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	return (status);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate  * Converts id to a wildcard string. e.g.:
3067c478bd9Sstevel@tonic-gate  *   For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \*
3077c478bd9Sstevel@tonic-gate  *   For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;*
3087c478bd9Sstevel@tonic-gate  *
3097c478bd9Sstevel@tonic-gate  * Returns NULL if id is already a wild-card.
3107c478bd9Sstevel@tonic-gate  */
3117c478bd9Sstevel@tonic-gate char *
3127c478bd9Sstevel@tonic-gate _exec_wild_id(char *id, const char *type)
3137c478bd9Sstevel@tonic-gate {
3147c478bd9Sstevel@tonic-gate 	char	c_id = '/';
3157c478bd9Sstevel@tonic-gate 	char	*pchar = NULL;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	if ((id == NULL) || (type == NULL))
3187c478bd9Sstevel@tonic-gate 		return (NULL);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	if (strcmp(type, KV_ACTION) == 0) {
3217c478bd9Sstevel@tonic-gate 		return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL :
3227c478bd9Sstevel@tonic-gate 		    KV_ACTION_WILDCARD);
3237c478bd9Sstevel@tonic-gate 	} else if (strcmp(type, KV_COMMAND) == 0) {
3247c478bd9Sstevel@tonic-gate 		if ((pchar = rindex(id, c_id)) == NULL)
3257c478bd9Sstevel@tonic-gate 			/*
3267c478bd9Sstevel@tonic-gate 			 * id = \*
3277c478bd9Sstevel@tonic-gate 			 */
3287c478bd9Sstevel@tonic-gate 			return (NULL);
3297c478bd9Sstevel@tonic-gate 		else if (*(++pchar) == KV_WILDCHAR)
3307c478bd9Sstevel@tonic-gate 			/*
3317c478bd9Sstevel@tonic-gate 			 * id = /usr/ccs/bin/\*
3327c478bd9Sstevel@tonic-gate 			 */
3337c478bd9Sstevel@tonic-gate 			return (pchar);
3347c478bd9Sstevel@tonic-gate 		/*
3357c478bd9Sstevel@tonic-gate 		 * id = /usr/ccs/bin/what
3367c478bd9Sstevel@tonic-gate 		 */
33761961e0fSrobinson 		(void) strcpy(pchar, KV_WILDCARD);
3387c478bd9Sstevel@tonic-gate 		return (id);
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	return (NULL);
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate execstr_t *
3477c478bd9Sstevel@tonic-gate _dup_execstr(execstr_t *old_exec)
3487c478bd9Sstevel@tonic-gate {
34961961e0fSrobinson 	execstr_t *new_exec = NULL;
3507c478bd9Sstevel@tonic-gate 
35161961e0fSrobinson 	if (old_exec == NULL)
35261961e0fSrobinson 		return (NULL);
35361961e0fSrobinson 	if ((new_exec = malloc(sizeof (execstr_t))) != NULL) {
3547c478bd9Sstevel@tonic-gate 		new_exec->name = _strdup_null(old_exec->name);
3557c478bd9Sstevel@tonic-gate 		new_exec->type = _strdup_null(old_exec->type);
3567c478bd9Sstevel@tonic-gate 		new_exec->policy = _strdup_null(old_exec->policy);
3577c478bd9Sstevel@tonic-gate 		new_exec->res1 = _strdup_null(old_exec->res1);
3587c478bd9Sstevel@tonic-gate 		new_exec->res2 = _strdup_null(old_exec->res2);
3597c478bd9Sstevel@tonic-gate 		new_exec->id = _strdup_null(old_exec->id);
3607c478bd9Sstevel@tonic-gate 		new_exec->attr = _strdup_null(old_exec->attr);
3617c478bd9Sstevel@tonic-gate 		new_exec->next = old_exec->next;
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate 	return (new_exec);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate void
3677c478bd9Sstevel@tonic-gate _free_execstr(execstr_t *exec)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	if (exec != NULL) {
3707c478bd9Sstevel@tonic-gate 		free(exec->name);
3717c478bd9Sstevel@tonic-gate 		free(exec->type);
3727c478bd9Sstevel@tonic-gate 		free(exec->policy);
3737c478bd9Sstevel@tonic-gate 		free(exec->res1);
3747c478bd9Sstevel@tonic-gate 		free(exec->res2);
3757c478bd9Sstevel@tonic-gate 		free(exec->id);
3767c478bd9Sstevel@tonic-gate 		free(exec->attr);
3777c478bd9Sstevel@tonic-gate 		_free_execstr(exec->next);
3787c478bd9Sstevel@tonic-gate 		free(exec);
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate void
3837c478bd9Sstevel@tonic-gate _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp)
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (res == NSS_SUCCESS) {
3887c478bd9Sstevel@tonic-gate 		if (_priv_exec->head_exec != NULL) {
3897c478bd9Sstevel@tonic-gate 			argp->buf.result = _priv_exec->head_exec;
3907c478bd9Sstevel@tonic-gate 			argp->returnval = argp->buf.result;
3917c478bd9Sstevel@tonic-gate 		}
3927c478bd9Sstevel@tonic-gate 	} else {
3937c478bd9Sstevel@tonic-gate 		if (_priv_exec->head_exec != NULL)
3947c478bd9Sstevel@tonic-gate 			_free_execstr(_priv_exec->head_exec);
3957c478bd9Sstevel@tonic-gate 		argp->returnval = NULL;
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate }
398