xref: /onnv-gate/usr/src/lib/libnsl/nss/getexecattr.c (revision 10020:ff5f2b3729b6)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*10020SJoep.Vesseur@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include "mt.h"
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <nss_dbdefs.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <strings.h>
330Sstevel@tonic-gate #include <sys/systeminfo.h>
340Sstevel@tonic-gate #include <thread.h>
350Sstevel@tonic-gate #include <synch.h>
360Sstevel@tonic-gate #include <nsswitch.h>
370Sstevel@tonic-gate #include <prof_attr.h>
380Sstevel@tonic-gate #include <exec_attr.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /* externs from libc */
410Sstevel@tonic-gate extern void _nss_db_state_destr(struct nss_db_state *);
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /* externs from parse.c */
440Sstevel@tonic-gate extern char *_strtok_escape(char *, char *, char **);
450Sstevel@tonic-gate extern char *_strdup_null(char *);
460Sstevel@tonic-gate /* extern from getprofattr.c */
470Sstevel@tonic-gate extern int str2profattr(const char *, int, void *, char *, int);
480Sstevel@tonic-gate 
490Sstevel@tonic-gate char *_exec_wild_id(char *, const char *);
500Sstevel@tonic-gate execstr_t *_dup_execstr(execstr_t *);
510Sstevel@tonic-gate void _free_execstr(execstr_t *);
520Sstevel@tonic-gate 
530Sstevel@tonic-gate static char *_nsw_search_path = NULL;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate  * Unsynchronized, but it affects only efficiency, not correctness
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(exec_root);
600Sstevel@tonic-gate static DEFINE_NSS_GETENT(context);
610Sstevel@tonic-gate 
620Sstevel@tonic-gate void
_nss_initf_execattr(nss_db_params_t * p)630Sstevel@tonic-gate _nss_initf_execattr(nss_db_params_t *p)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate 	p->name = NSS_DBNAM_EXECATTR;
660Sstevel@tonic-gate 	p->config_name    = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */
670Sstevel@tonic-gate }
680Sstevel@tonic-gate 
690Sstevel@tonic-gate void
_nsw_initf_execattr(nss_db_params_t * p)700Sstevel@tonic-gate _nsw_initf_execattr(nss_db_params_t *p)
710Sstevel@tonic-gate {
720Sstevel@tonic-gate 	p->name = NSS_DBNAM_EXECATTR;
730Sstevel@tonic-gate 	p->flags |= NSS_USE_DEFAULT_CONFIG;
740Sstevel@tonic-gate 	p->default_config = _nsw_search_path;
750Sstevel@tonic-gate }
760Sstevel@tonic-gate 
770Sstevel@tonic-gate void
_nsw_initf_profattr(nss_db_params_t * p)780Sstevel@tonic-gate _nsw_initf_profattr(nss_db_params_t *p)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate 	p->name = NSS_DBNAM_PROFATTR;
810Sstevel@tonic-gate 	p->flags |= NSS_USE_DEFAULT_CONFIG;
820Sstevel@tonic-gate 	p->default_config = _nsw_search_path;
830Sstevel@tonic-gate }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate  * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure
870Sstevel@tonic-gate  * pointer passed in is a structure in the caller's space wherein the field
880Sstevel@tonic-gate  * pointers would be set to areas in the buffer if need be. instring and buffer
890Sstevel@tonic-gate  * should be separate areas.
900Sstevel@tonic-gate  */
910Sstevel@tonic-gate int
str2execattr(const char * instr,int lenstr,void * ent,char * buffer,int buflen)920Sstevel@tonic-gate str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
930Sstevel@tonic-gate {
94132Srobinson 	char		*last = NULL;
950Sstevel@tonic-gate 	char		*sep = KV_TOKEN_DELIMIT;
960Sstevel@tonic-gate 	execstr_t	*exec = (execstr_t *)ent;
970Sstevel@tonic-gate 
98132Srobinson 	if (lenstr >= buflen)
990Sstevel@tonic-gate 		return (NSS_STR_PARSE_ERANGE);
1002830Sdjl 
1012830Sdjl 	if (instr != buffer)
1022830Sdjl 		(void) strncpy(buffer, instr, buflen);
1032830Sdjl 
1040Sstevel@tonic-gate 	/*
1050Sstevel@tonic-gate 	 * Remove newline that nis (yp_match) puts at the
1060Sstevel@tonic-gate 	 * end of the entry it retrieves from the map.
1070Sstevel@tonic-gate 	 */
1080Sstevel@tonic-gate 	if (buffer[lenstr] == '\n') {
1090Sstevel@tonic-gate 		buffer[lenstr] = '\0';
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 
1122830Sdjl 	/* quick exit do not entry fill if not needed */
1132830Sdjl 	if (ent == (void *)NULL)
1142830Sdjl 		return (NSS_STR_PARSE_SUCCESS);
1152830Sdjl 
1160Sstevel@tonic-gate 	exec->name = _strtok_escape(buffer, sep, &last);
1170Sstevel@tonic-gate 	exec->policy = _strtok_escape(NULL, sep, &last);
1180Sstevel@tonic-gate 	exec->type = _strtok_escape(NULL, sep, &last);
1190Sstevel@tonic-gate 	exec->res1 = _strtok_escape(NULL, sep, &last);
1200Sstevel@tonic-gate 	exec->res2 = _strtok_escape(NULL, sep, &last);
1210Sstevel@tonic-gate 	exec->id = _strtok_escape(NULL, sep, &last);
1220Sstevel@tonic-gate 	exec->attr = _strtok_escape(NULL, sep, &last);
123132Srobinson 	exec->next = NULL;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	return (NSS_STR_PARSE_SUCCESS);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate void
_setexecattr(void)1300Sstevel@tonic-gate _setexecattr(void)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate 	nss_setent(&exec_root, _nss_initf_execattr, &context);
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate void
_endexecattr(void)1370Sstevel@tonic-gate _endexecattr(void)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	nss_endent(&exec_root, _nss_initf_execattr, &context);
1400Sstevel@tonic-gate 	nss_delete(&exec_root);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate execstr_t *
_getexecattr(execstr_t * result,char * buffer,int buflen,int * errnop)1450Sstevel@tonic-gate _getexecattr(execstr_t *result, char *buffer, int buflen, int *errnop)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 	nss_status_t    res;
1480Sstevel@tonic-gate 	nss_XbyY_args_t arg;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
1510Sstevel@tonic-gate 	res = nss_getent(&exec_root, _nss_initf_execattr, &context, &arg);
1520Sstevel@tonic-gate 	arg.status = res;
1530Sstevel@tonic-gate 	*errnop = arg.h_errno;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate execstr_t *
_getexecprof(char * name,char * type,char * id,int search_flag,execstr_t * result,char * buffer,int buflen,int * errnop)1590Sstevel@tonic-gate _getexecprof(char *name,
1600Sstevel@tonic-gate     char *type,
1610Sstevel@tonic-gate     char *id,
1620Sstevel@tonic-gate     int search_flag,
1630Sstevel@tonic-gate     execstr_t *result,
1640Sstevel@tonic-gate     char *buffer,
1650Sstevel@tonic-gate     int buflen,
1660Sstevel@tonic-gate     int *errnop)
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate 	int		getby_flag;
1690Sstevel@tonic-gate 	char		policy_buf[BUFSIZ];
170132Srobinson 	const char	*empty = NULL;
1710Sstevel@tonic-gate 	nss_status_t	res = NSS_NOTFOUND;
1720Sstevel@tonic-gate 	nss_XbyY_args_t	arg;
1730Sstevel@tonic-gate 	_priv_execattr	_priv_exec;
1740Sstevel@tonic-gate 	static mutex_t	_nsw_exec_lock = DEFAULTMUTEX;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	_priv_exec.name = (name == NULL) ? empty : (const char *)name;
1790Sstevel@tonic-gate 	_priv_exec.type = (type == NULL) ? empty : (const char *)type;
1800Sstevel@tonic-gate 	_priv_exec.id = (id == NULL) ? empty : (const char *)id;
1810Sstevel@tonic-gate #ifdef SI_SECPOLICY
1820Sstevel@tonic-gate 	if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1)
1830Sstevel@tonic-gate #endif	/* SI_SECPOLICY */
184132Srobinson 	(void) strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ);
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate retry_policy:
187*10020SJoep.Vesseur@Sun.COM 	_priv_exec.policy = IS_SEARCH_ALL(search_flag) ? empty : policy_buf;
1880Sstevel@tonic-gate 	_priv_exec.search_flag = search_flag;
189132Srobinson 	_priv_exec.head_exec = NULL;
190132Srobinson 	_priv_exec.prev_exec = NULL;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	if ((name != NULL) && (id != NULL)) {
1930Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYNAMEID;
1940Sstevel@tonic-gate 	} else if (name != NULL) {
1950Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYNAME;
1960Sstevel@tonic-gate 	} else if (id != NULL) {
1970Sstevel@tonic-gate 		getby_flag = NSS_DBOP_EXECATTR_BYID;
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	arg.key.attrp = &(_priv_exec);
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	switch (getby_flag) {
2030Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYID:
2040Sstevel@tonic-gate 		res = nss_search(&exec_root, _nss_initf_execattr, getby_flag,
2050Sstevel@tonic-gate 		    &arg);
2060Sstevel@tonic-gate 		break;
2070Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYNAMEID:
2080Sstevel@tonic-gate 	case NSS_DBOP_EXECATTR_BYNAME:
2090Sstevel@tonic-gate 		{
2100Sstevel@tonic-gate 			char			pbuf[NSS_BUFLEN_PROFATTR];
2110Sstevel@tonic-gate 			profstr_t		prof;
2120Sstevel@tonic-gate 			nss_status_t		pres;
2130Sstevel@tonic-gate 			nss_XbyY_args_t		parg;
2140Sstevel@tonic-gate 			enum __nsw_parse_err	pserr;
2150Sstevel@tonic-gate 			struct __nsw_lookup	*lookups = NULL;
2160Sstevel@tonic-gate 			struct __nsw_switchconfig *conf = NULL;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 			if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr))
2190Sstevel@tonic-gate 				if ((lookups = conf->lookups) == NULL)
2200Sstevel@tonic-gate 					goto out;
2210Sstevel@tonic-gate 			NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR,
2220Sstevel@tonic-gate 			    str2profattr);
2230Sstevel@tonic-gate 			parg.key.name = name;
2240Sstevel@tonic-gate 			do {
2250Sstevel@tonic-gate 				/*
2260Sstevel@tonic-gate 				 * search the exec_attr entry only in the scope
2270Sstevel@tonic-gate 				 * that we find the profile in.
2280Sstevel@tonic-gate 				 * if conf = NULL, search in local files only,
2290Sstevel@tonic-gate 				 * as we were not able to read nsswitch.conf.
2300Sstevel@tonic-gate 				 */
2310Sstevel@tonic-gate 				DEFINE_NSS_DB_ROOT(prof_root);
2320Sstevel@tonic-gate 				if (mutex_lock(&_nsw_exec_lock) != 0)
2330Sstevel@tonic-gate 					goto out;
2340Sstevel@tonic-gate 				_nsw_search_path = (conf == NULL)
2350Sstevel@tonic-gate 				    ? NSS_FILES_ONLY
2360Sstevel@tonic-gate 				    : lookups->service_name;
2370Sstevel@tonic-gate 				pres = nss_search(&prof_root,
2380Sstevel@tonic-gate 				    _nsw_initf_profattr,
2390Sstevel@tonic-gate 				    NSS_DBOP_PROFATTR_BYNAME, &parg);
2400Sstevel@tonic-gate 				if (pres == NSS_SUCCESS) {
2410Sstevel@tonic-gate 					DEFINE_NSS_DB_ROOT(pexec_root);
2420Sstevel@tonic-gate 					res = nss_search(&pexec_root,
2430Sstevel@tonic-gate 					    _nsw_initf_execattr, getby_flag,
2440Sstevel@tonic-gate 					    &arg);
2452830Sdjl 					if (pexec_root.s != NULL)
2462830Sdjl 						_nss_db_state_destr(
247*10020SJoep.Vesseur@Sun.COM 						    pexec_root.s);
2480Sstevel@tonic-gate 				}
2492830Sdjl 				if (prof_root.s != NULL)
2502830Sdjl 					_nss_db_state_destr(prof_root.s);
2510Sstevel@tonic-gate 				(void) mutex_unlock(&_nsw_exec_lock);
2520Sstevel@tonic-gate 				if ((pres == NSS_SUCCESS) || (conf == NULL))
2530Sstevel@tonic-gate 					break;
2540Sstevel@tonic-gate 			} while (lookups && (lookups = lookups->next));
2550Sstevel@tonic-gate 		}
2560Sstevel@tonic-gate 		break;
2570Sstevel@tonic-gate 	default:
2580Sstevel@tonic-gate 		break;
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate out:
2620Sstevel@tonic-gate 	/*
2630Sstevel@tonic-gate 	 * If we can't find an entry for the current default policy
2640Sstevel@tonic-gate 	 * fall back to the old "suser" policy.  The nameservice is
2650Sstevel@tonic-gate 	 * shared between different OS releases.
2660Sstevel@tonic-gate 	 */
267*10020SJoep.Vesseur@Sun.COM 	if (!IS_SEARCH_ALL(search_flag) &&
268*10020SJoep.Vesseur@Sun.COM 	    (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0)) {
2690Sstevel@tonic-gate 		(void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ);
2700Sstevel@tonic-gate 		goto retry_policy;
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	arg.status = res;
2740Sstevel@tonic-gate 	*errnop = res;
2750Sstevel@tonic-gate 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate int
_doexeclist(nss_XbyY_args_t * argp)2800Sstevel@tonic-gate _doexeclist(nss_XbyY_args_t *argp)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate 	int		status = 1;
2830Sstevel@tonic-gate 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
2840Sstevel@tonic-gate 	execstr_t	*exec = (execstr_t *)((argp->buf.result));
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	if (_priv_exec->head_exec == NULL) {
2870Sstevel@tonic-gate 		if (_priv_exec->head_exec = _dup_execstr(exec))
2880Sstevel@tonic-gate 			_priv_exec->prev_exec = _priv_exec->head_exec;
2890Sstevel@tonic-gate 		else
2900Sstevel@tonic-gate 			status = 0;
2910Sstevel@tonic-gate 	} else {
2920Sstevel@tonic-gate 		if (_priv_exec->prev_exec->next = _dup_execstr(exec))
2930Sstevel@tonic-gate 			_priv_exec->prev_exec = _priv_exec->prev_exec->next;
2940Sstevel@tonic-gate 		else
2950Sstevel@tonic-gate 			status = 0;
2960Sstevel@tonic-gate 	}
297132Srobinson 	(void) memset(argp->buf.buffer, NULL, argp->buf.buflen);
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	return (status);
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate  * Converts id to a wildcard string. e.g.:
3060Sstevel@tonic-gate  *   For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \*
3070Sstevel@tonic-gate  *   For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;*
3080Sstevel@tonic-gate  *
3090Sstevel@tonic-gate  * Returns NULL if id is already a wild-card.
3100Sstevel@tonic-gate  */
3110Sstevel@tonic-gate char *
_exec_wild_id(char * id,const char * type)3120Sstevel@tonic-gate _exec_wild_id(char *id, const char *type)
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate 	char	c_id = '/';
3150Sstevel@tonic-gate 	char	*pchar = NULL;
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	if ((id == NULL) || (type == NULL))
3180Sstevel@tonic-gate 		return (NULL);
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	if (strcmp(type, KV_ACTION) == 0) {
3210Sstevel@tonic-gate 		return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL :
3220Sstevel@tonic-gate 		    KV_ACTION_WILDCARD);
3230Sstevel@tonic-gate 	} else if (strcmp(type, KV_COMMAND) == 0) {
3240Sstevel@tonic-gate 		if ((pchar = rindex(id, c_id)) == NULL)
3250Sstevel@tonic-gate 			/*
3260Sstevel@tonic-gate 			 * id = \*
3270Sstevel@tonic-gate 			 */
3280Sstevel@tonic-gate 			return (NULL);
3290Sstevel@tonic-gate 		else if (*(++pchar) == KV_WILDCHAR)
3300Sstevel@tonic-gate 			/*
3310Sstevel@tonic-gate 			 * id = /usr/ccs/bin/\*
3320Sstevel@tonic-gate 			 */
3330Sstevel@tonic-gate 			return (pchar);
3340Sstevel@tonic-gate 		/*
3350Sstevel@tonic-gate 		 * id = /usr/ccs/bin/what
3360Sstevel@tonic-gate 		 */
337132Srobinson 		(void) strcpy(pchar, KV_WILDCARD);
3380Sstevel@tonic-gate 		return (id);
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	return (NULL);
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate execstr_t *
_dup_execstr(execstr_t * old_exec)3470Sstevel@tonic-gate _dup_execstr(execstr_t *old_exec)
3480Sstevel@tonic-gate {
349132Srobinson 	execstr_t *new_exec = NULL;
3500Sstevel@tonic-gate 
351132Srobinson 	if (old_exec == NULL)
352132Srobinson 		return (NULL);
353132Srobinson 	if ((new_exec = malloc(sizeof (execstr_t))) != NULL) {
3540Sstevel@tonic-gate 		new_exec->name = _strdup_null(old_exec->name);
3550Sstevel@tonic-gate 		new_exec->type = _strdup_null(old_exec->type);
3560Sstevel@tonic-gate 		new_exec->policy = _strdup_null(old_exec->policy);
3570Sstevel@tonic-gate 		new_exec->res1 = _strdup_null(old_exec->res1);
3580Sstevel@tonic-gate 		new_exec->res2 = _strdup_null(old_exec->res2);
3590Sstevel@tonic-gate 		new_exec->id = _strdup_null(old_exec->id);
3600Sstevel@tonic-gate 		new_exec->attr = _strdup_null(old_exec->attr);
3610Sstevel@tonic-gate 		new_exec->next = old_exec->next;
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate 	return (new_exec);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate void
_free_execstr(execstr_t * exec)3670Sstevel@tonic-gate _free_execstr(execstr_t *exec)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate 	if (exec != NULL) {
3700Sstevel@tonic-gate 		free(exec->name);
3710Sstevel@tonic-gate 		free(exec->type);
3720Sstevel@tonic-gate 		free(exec->policy);
3730Sstevel@tonic-gate 		free(exec->res1);
3740Sstevel@tonic-gate 		free(exec->res2);
3750Sstevel@tonic-gate 		free(exec->id);
3760Sstevel@tonic-gate 		free(exec->attr);
3770Sstevel@tonic-gate 		_free_execstr(exec->next);
3780Sstevel@tonic-gate 		free(exec);
3790Sstevel@tonic-gate 	}
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate void
_exec_cleanup(nss_status_t res,nss_XbyY_args_t * argp)3830Sstevel@tonic-gate _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	if (res == NSS_SUCCESS) {
3880Sstevel@tonic-gate 		if (_priv_exec->head_exec != NULL) {
3890Sstevel@tonic-gate 			argp->buf.result = _priv_exec->head_exec;
3900Sstevel@tonic-gate 			argp->returnval = argp->buf.result;
3910Sstevel@tonic-gate 		}
3920Sstevel@tonic-gate 	} else {
3930Sstevel@tonic-gate 		if (_priv_exec->head_exec != NULL)
3940Sstevel@tonic-gate 			_free_execstr(_priv_exec->head_exec);
3950Sstevel@tonic-gate 		argp->returnval = NULL;
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate }
398