diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/nsswitch/files/common/getexecattr.c | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/nsswitch/files/common/getexecattr.c')
-rw-r--r-- | usr/src/lib/nsswitch/files/common/getexecattr.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/usr/src/lib/nsswitch/files/common/getexecattr.c b/usr/src/lib/nsswitch/files/common/getexecattr.c new file mode 100644 index 0000000000..2c5f5b482d --- /dev/null +++ b/usr/src/lib/nsswitch/files/common/getexecattr.c @@ -0,0 +1,377 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> +#include "files_common.h" +#include <time.h> +#include <exec_attr.h> +#include <strings.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <ctype.h> +#include <synch.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> + +/* + * files/getexecattr.c -- "files" backend for nsswitch "exec_attr" database + * + * _execattr_files_read_line and _execattr_files_XY_all code based on + * nss_files_read_line and nss_files_XY_all respectively, from files_common.c + */ + + +/* externs from libnsl */ +extern int _doexeclist(nss_XbyY_args_t *); +extern int _readbufline(char *, int, char *, int, int *); +extern char *_exec_wild_id(char *, const char *); +extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *); + +typedef int (*_exec_XY_check_func) (nss_XbyY_args_t *); + + +/* + * check_match: returns 1 if matching entry found, else returns 0. + */ +static int +check_match(nss_XbyY_args_t *argp) +{ + _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); + const char *name = _priv_exec->name; + const char *type = _priv_exec->type; + const char *id = _priv_exec->id; + const char *policy = _priv_exec->policy; + execstr_t *exec = (execstr_t *)argp->returnval; + + if ((policy && exec->policy && (strcmp(policy, exec->policy) != 0)) || + (name && exec->name && (strcmp(name, exec->name) != 0)) || + (type && exec->type && (strcmp(type, exec->type) != 0)) || + (id && exec->id && (strcmp(id, exec->id) != 0))) { + return (0); + } + + return (1); +} + + +static nss_status_t +_exec_files_XY_all(files_backend_ptr_t be, + nss_XbyY_args_t *argp, + int getby_flag) +{ + int parse_stat = 0; + int lastlen = 0; + int exec_fd = 0; + int f_size = 0; + time_t f_time = 0; + static time_t read_time = 0; + char *key = NULL; + char *first; + char *last; + static char *f_buf = NULL; + struct stat f_stat; + nss_status_t res = NSS_NOTFOUND; + _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); + static rwlock_t exec_lock; + + if (((be->buf == NULL) && + ((be->buf = (char *)calloc(1, be->minbuf)) == NULL)) || + (be->filename == NULL) || + (rw_rdlock(&exec_lock) != 0)) { + return (NSS_UNAVAIL); + } + + /* + * check the size and the time stamp on the file + */ + if (stat(be->filename, &f_stat) != 0) { + (void) _nss_files_endent(be, 0); + (void) rw_unlock(&exec_lock); + return (NSS_UNAVAIL); + } + + f_size = f_stat.st_size; + f_time = f_stat.st_mtime; + + while (f_time > read_time) { + /* + * file has been modified since we last read it. + * read it into the buffer with rw lock. + */ + (void) rw_unlock(&exec_lock); + if (rw_wrlock(&exec_lock) != 0) { + (void) _nss_files_endent(be, 0); + return (NSS_UNAVAIL); + } + if ((be->f = __nsl_fopen(be->filename, "r")) == 0) { + (void) _nss_files_endent(be, 0); + (void) rw_unlock(&exec_lock); + return (NSS_UNAVAIL); + } + exec_fd = __nsl_fileno(be->f); + if (f_buf != NULL) + free(f_buf); + if ((f_buf = malloc(f_size)) == NULL) { + (void) _nss_files_endent(be, 0); + (void) rw_unlock(&exec_lock); + return (NSS_UNAVAIL); + } + if (read(exec_fd, f_buf, f_size) < f_size) { + free(f_buf); + (void) _nss_files_endent(be, 0); + (void) rw_unlock(&exec_lock); + return (NSS_UNAVAIL); + } + read_time = f_time; + (void) rw_unlock(&exec_lock); + /* + * verify that the file did not change after + * we read it. + */ + if (rw_rdlock(&exec_lock) != 0) { + free(f_buf); + (void) _nss_files_endent(be, 0); + return (NSS_UNAVAIL); + } + if (stat(be->filename, &f_stat) != 0) { + free(f_buf); + (void) _nss_files_endent(be, 0); + (void) rw_unlock(&exec_lock); + return (NSS_UNAVAIL); + } + f_size = f_stat.st_size; + f_time = f_stat.st_mtime; + } + + res = NSS_NOTFOUND; + while (1) { + int linelen = 0; + int check_stat = 0; + char *instr = be->buf; + + linelen = _readbufline(f_buf, f_size, instr, be->minbuf, + &lastlen); + if (linelen < 0) { + /* End of file */ + argp->erange = 0; + break; + } + + /* + * If the entry doesn't contain the filter string then + * it can't be the entry we want, so don't bother looking + * more closely at it. + */ + switch (getby_flag) { + case NSS_DBOP_EXECATTR_BYNAME: + if (strstr(instr, _priv_exec->name) == NULL) + continue; + break; + case NSS_DBOP_EXECATTR_BYID: + if (strstr(instr, _priv_exec->id) == NULL) + continue; + break; + case NSS_DBOP_EXECATTR_BYNAMEID: + if ((strstr(instr, _priv_exec->name) == NULL) || + (strstr(instr, _priv_exec->id) == NULL)) + continue; + break; + default: + break; + } + if ((strstr(instr, _priv_exec->policy) == NULL) || + ((_priv_exec->type != NULL) && + (strstr(instr, _priv_exec->type) == NULL))) + continue; + + /* + * Get rid of white spaces, comments etc. + */ + if ((last = strchr(instr, '#')) == NULL) + last = instr + linelen; + *last-- = '\0'; /* Nuke '\n' or #comment */ + /* + * Skip leading whitespace. Normally there isn't any, + * so it's not worth calling strspn(). + */ + for (first = instr; isspace(*first); first++) + ; + if (*first == '\0') + continue; + /* + * Found something non-blank on the line. Skip back + * over any trailing whitespace; since we know there's + * non-whitespace earlier in the line, checking for + * termination is easy. + */ + while (isspace(*last)) + --last; + linelen = last - first + 1; + if (first != instr) + instr = first; + + /* + * Parse the entry. + */ + argp->returnval = NULL; + parse_stat = (*argp->str2ent)(instr, linelen, argp->buf.result, + argp->buf.buffer, argp->buf.buflen); + if (parse_stat == NSS_STR_PARSE_SUCCESS) { + argp->returnval = argp->buf.result; + if (check_match(argp)) { + res = NSS_SUCCESS; + if (_priv_exec->search_flag == GET_ONE) { + break; + } else if (_doexeclist(argp) == 0) { + res = NSS_UNAVAIL; + break; + } + } else { + argp->returnval = NULL; + memset(argp->buf.buffer, NULL, + argp->buf.buflen); + } + } else if (parse_stat == NSS_STR_PARSE_ERANGE) { + argp->erange = 1; + break; + } /* else if (parse_stat == NSS_STR_PARSE_PARSE) don't care ! */ + } + + (void) _nss_files_endent(be, 0); + (void) rw_unlock(&exec_lock); + + return (res); +} + + +/* + * If search for exact match for id failed, get_wild checks if we have + * a wild-card entry for that id. + */ +static nss_status_t +get_wild(files_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag) +{ + char *orig_id = NULL; + char *old_id = NULL; + char *wild_id = NULL; + nss_status_t res = NSS_NOTFOUND; + _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); + + orig_id = strdup(_priv_exec->id); + old_id = strdup(_priv_exec->id); + wild_id = old_id; + while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) { + _priv_exec->id = wild_id; + res = _exec_files_XY_all(be, argp, getby_flag); + if (res == NSS_SUCCESS) + break; + } + _priv_exec->id = orig_id; + if (old_id) + free(old_id); + + return (res); +} + + +static nss_status_t +getbynam(files_backend_ptr_t be, void *a) +{ + nss_status_t res; + nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; + + res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYNAME); + + _exec_cleanup(res, argp); + + return (res); +} + + +static nss_status_t +getbyid(files_backend_ptr_t be, void *a) +{ + nss_status_t res; + nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; + _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); + + res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYID); + + if (res != NSS_SUCCESS) + res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID); + + _exec_cleanup(res, argp); + + return (res); +} + + +static nss_status_t +getbynameid(files_backend_ptr_t be, void *a) +{ + nss_status_t res; + nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; + _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); + + res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); + + if (res != NSS_SUCCESS) + res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); + + _exec_cleanup(res, argp); + + return (res); +} + + +static files_backend_op_t execattr_ops[] = { + _nss_files_destr, + _nss_files_endent, + _nss_files_setent, + _nss_files_getent_netdb, + getbynam, + getbyid, + getbynameid +}; + +nss_backend_t * +_nss_files_exec_attr_constr(const char *dummy1, + const char *dummy2, + const char *dummy3, + const char *dummy4, + const char *dummy5, + const char *dummy6, + const char *dummy7) +{ + return (_nss_files_constr(execattr_ops, + sizeof (execattr_ops)/sizeof (execattr_ops[0]), + EXECATTR_FILENAME, + NSS_LINELEN_EXECATTR, + NULL)); +} |