import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / nsl / getexecattr.c
blobdad35deb3aa8455a0e3962d70cd79d2ae7d038cb
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
29 #include "mt.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <nss_dbdefs.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <sys/systeminfo.h>
37 #include <thread.h>
38 #include <synch.h>
39 #include <nsswitch.h>
40 #include <prof_attr.h>
41 #include <exec_attr.h>
43 /* externs from libc */
44 extern void _nss_db_state_destr(struct nss_db_state *);
46 /* externs from parse.c */
47 extern char *_strtok_escape(char *, char *, char **);
48 extern char *_strdup_null(char *);
49 /* extern from getprofattr.c */
50 extern int str2profattr(const char *, int, void *, char *, int);
52 char *_exec_wild_id(char *, const char *);
53 execstr_t *_dup_execstr(execstr_t *);
54 void _free_execstr(execstr_t *);
56 static char *_nsw_search_path = NULL;
59 * Unsynchronized, but it affects only efficiency, not correctness
62 static DEFINE_NSS_DB_ROOT(exec_root);
63 static DEFINE_NSS_GETENT(context);
65 void
66 _nss_initf_execattr(nss_db_params_t *p)
68 p->name = NSS_DBNAM_EXECATTR;
69 p->config_name = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */
72 void
73 _nsw_initf_execattr(nss_db_params_t *p)
75 p->name = NSS_DBNAM_EXECATTR;
76 p->flags |= NSS_USE_DEFAULT_CONFIG;
77 p->default_config = _nsw_search_path;
80 void
81 _nsw_initf_profattr(nss_db_params_t *p)
83 p->name = NSS_DBNAM_PROFATTR;
84 p->flags |= NSS_USE_DEFAULT_CONFIG;
85 p->default_config = _nsw_search_path;
89 * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure
90 * pointer passed in is a structure in the caller's space wherein the field
91 * pointers would be set to areas in the buffer if need be. instring and buffer
92 * should be separate areas.
94 int
95 str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
97 char *last = NULL;
98 char *sep = KV_TOKEN_DELIMIT;
99 execstr_t *exec = (execstr_t *)ent;
101 if (lenstr >= buflen)
102 return (NSS_STR_PARSE_ERANGE);
104 if (instr != buffer)
105 (void) strncpy(buffer, instr, buflen);
108 * Remove newline that nis (yp_match) puts at the
109 * end of the entry it retrieves from the map.
111 if (buffer[lenstr] == '\n') {
112 buffer[lenstr] = '\0';
115 /* quick exit do not entry fill if not needed */
116 if (ent == NULL)
117 return (NSS_STR_PARSE_SUCCESS);
119 exec->name = _strtok_escape(buffer, sep, &last);
120 exec->policy = _strtok_escape(NULL, sep, &last);
121 exec->type = _strtok_escape(NULL, sep, &last);
122 exec->res1 = _strtok_escape(NULL, sep, &last);
123 exec->res2 = _strtok_escape(NULL, sep, &last);
124 exec->id = _strtok_escape(NULL, sep, &last);
125 exec->attr = _strtok_escape(NULL, sep, &last);
126 exec->next = NULL;
128 return (NSS_STR_PARSE_SUCCESS);
132 void
133 _setexecattr(void)
135 nss_setent(&exec_root, _nss_initf_execattr, &context);
139 void
140 _endexecattr(void)
142 nss_endent(&exec_root, _nss_initf_execattr, &context);
143 nss_delete(&exec_root);
147 execstr_t *
148 _getexecattr(execstr_t *result, char *buffer, int buflen, int *errnop)
150 nss_status_t res;
151 nss_XbyY_args_t arg;
153 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
154 res = nss_getent(&exec_root, _nss_initf_execattr, &context, &arg);
155 arg.status = res;
156 *errnop = arg.h_errno;
158 return ((execstr_t *)NSS_XbyY_FINI(&arg));
161 execstr_t *
162 _getexecprof(char *name,
163 char *type,
164 char *id,
165 int search_flag,
166 execstr_t *result,
167 char *buffer,
168 int buflen,
169 int *errnop)
171 int getby_flag;
172 char policy_buf[BUFSIZ];
173 nss_status_t res = NSS_NOTFOUND;
174 nss_XbyY_args_t arg;
175 _priv_execattr _priv_exec;
176 static mutex_t _nsw_exec_lock = DEFAULTMUTEX;
178 if ((name != NULL) && (id != NULL)) {
179 getby_flag = NSS_DBOP_EXECATTR_BYNAMEID;
180 } else if (name != NULL) {
181 getby_flag = NSS_DBOP_EXECATTR_BYNAME;
182 } else if (id != NULL) {
183 getby_flag = NSS_DBOP_EXECATTR_BYID;
184 } else {
185 return (NULL);
188 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
190 _priv_exec.name = name;
191 _priv_exec.type = type;
192 _priv_exec.id = id;
193 #ifdef SI_SECPOLICY
194 if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1)
195 #endif /* SI_SECPOLICY */
196 (void) strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ);
198 retry_policy:
199 _priv_exec.policy = IS_SEARCH_ALL(search_flag) ? NULL : policy_buf;
200 _priv_exec.search_flag = search_flag;
201 _priv_exec.head_exec = NULL;
202 _priv_exec.prev_exec = NULL;
204 arg.key.attrp = &(_priv_exec);
206 switch (getby_flag) {
207 case NSS_DBOP_EXECATTR_BYID:
208 res = nss_search(&exec_root, _nss_initf_execattr, getby_flag,
209 &arg);
210 break;
211 case NSS_DBOP_EXECATTR_BYNAMEID:
212 case NSS_DBOP_EXECATTR_BYNAME:
214 char pbuf[NSS_BUFLEN_PROFATTR];
215 profstr_t prof;
216 nss_status_t pres;
217 nss_XbyY_args_t parg;
218 enum __nsw_parse_err pserr;
219 struct __nsw_lookup *lookups = NULL;
220 struct __nsw_switchconfig *conf = NULL;
222 if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr))
223 if ((lookups = conf->lookups) == NULL)
224 goto out;
225 NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR,
226 str2profattr);
227 parg.key.name = name;
228 do {
230 * search the exec_attr entry only in the scope
231 * that we find the profile in.
232 * if conf = NULL, search in local files only,
233 * as we were not able to read nsswitch.conf.
235 DEFINE_NSS_DB_ROOT(prof_root);
236 if (mutex_lock(&_nsw_exec_lock) != 0)
237 goto out;
238 _nsw_search_path = (conf == NULL)
239 ? NSS_FILES_ONLY
240 : lookups->service_name;
241 pres = nss_search(&prof_root,
242 _nsw_initf_profattr,
243 NSS_DBOP_PROFATTR_BYNAME, &parg);
244 if (pres == NSS_SUCCESS) {
245 DEFINE_NSS_DB_ROOT(pexec_root);
246 res = nss_search(&pexec_root,
247 _nsw_initf_execattr, getby_flag,
248 &arg);
249 if (pexec_root.s != NULL)
250 _nss_db_state_destr(
251 pexec_root.s);
253 if (prof_root.s != NULL)
254 _nss_db_state_destr(prof_root.s);
255 (void) mutex_unlock(&_nsw_exec_lock);
256 if ((pres == NSS_SUCCESS) || (conf == NULL))
257 break;
258 } while (lookups && (lookups = lookups->next));
260 break;
261 default:
262 break;
265 out:
267 * If we can't find an entry for the current default policy
268 * fall back to the old "suser" policy. The nameservice is
269 * shared between different OS releases.
271 if (!IS_SEARCH_ALL(search_flag) &&
272 (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0)) {
273 (void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ);
274 goto retry_policy;
277 arg.status = res;
278 *errnop = res;
279 return ((execstr_t *)NSS_XbyY_FINI(&arg));
284 _doexeclist(nss_XbyY_args_t *argp)
286 int status = 1;
287 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
288 execstr_t *exec = (execstr_t *)((argp->buf.result));
290 if (_priv_exec->head_exec == NULL) {
291 if (_priv_exec->head_exec = _dup_execstr(exec))
292 _priv_exec->prev_exec = _priv_exec->head_exec;
293 else
294 status = 0;
295 } else {
296 if (_priv_exec->prev_exec->next = _dup_execstr(exec))
297 _priv_exec->prev_exec = _priv_exec->prev_exec->next;
298 else
299 status = 0;
301 (void) memset(argp->buf.buffer, 0, argp->buf.buflen);
303 return (status);
309 * Converts id to a wildcard string. e.g.:
310 * For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \*
311 * For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;*
313 * Returns NULL if id is already a wild-card.
315 char *
316 _exec_wild_id(char *id, const char *type)
318 char c_id = '/';
319 char *pchar = NULL;
321 if ((id == NULL) || (type == NULL))
322 return (NULL);
324 if (strcmp(type, KV_ACTION) == 0) {
325 return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL :
326 KV_ACTION_WILDCARD);
327 } else if (strcmp(type, KV_COMMAND) == 0) {
328 if ((pchar = rindex(id, c_id)) == NULL)
330 * id = \*
332 return (NULL);
333 else if (*(++pchar) == KV_WILDCHAR)
335 * id = /usr/ccs/bin/\*
337 return (pchar);
339 * id = /usr/ccs/bin/what
341 (void) strcpy(pchar, KV_WILDCARD);
342 return (id);
345 return (NULL);
350 execstr_t *
351 _dup_execstr(execstr_t *old_exec)
353 execstr_t *new_exec = NULL;
355 if (old_exec == NULL)
356 return (NULL);
357 if ((new_exec = malloc(sizeof (execstr_t))) != NULL) {
358 new_exec->name = _strdup_null(old_exec->name);
359 new_exec->type = _strdup_null(old_exec->type);
360 new_exec->policy = _strdup_null(old_exec->policy);
361 new_exec->res1 = _strdup_null(old_exec->res1);
362 new_exec->res2 = _strdup_null(old_exec->res2);
363 new_exec->id = _strdup_null(old_exec->id);
364 new_exec->attr = _strdup_null(old_exec->attr);
365 new_exec->next = old_exec->next;
367 return (new_exec);
370 void
371 _free_execstr(execstr_t *exec)
373 if (exec != NULL) {
374 free(exec->name);
375 free(exec->type);
376 free(exec->policy);
377 free(exec->res1);
378 free(exec->res2);
379 free(exec->id);
380 free(exec->attr);
381 _free_execstr(exec->next);
382 free(exec);
386 void
387 _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp)
389 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
391 if (res == NSS_SUCCESS) {
392 if (_priv_exec->head_exec != NULL) {
393 argp->buf.result = _priv_exec->head_exec;
394 argp->returnval = argp->buf.result;
396 } else {
397 if (_priv_exec->head_exec != NULL)
398 _free_execstr(_priv_exec->head_exec);
399 argp->returnval = NULL;