summaryrefslogtreecommitdiff
path: root/usr/src/lib/nsswitch/files/common/getexecattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/nsswitch/files/common/getexecattr.c')
-rw-r--r--usr/src/lib/nsswitch/files/common/getexecattr.c377
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));
+}