#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <exec_attr.h>
#include <rpcsvc/ypclnt.h>
#include <rpcsvc/yp_prot.h>
#include "nis_common.h"
extern void massage_netdb(const char **, int *);
extern int _doexeclist(nss_XbyY_args_t *);
extern char *_exec_wild_id(char *, const char *);
extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
extern char *_strtok_escape(char *, char *, char **);
typedef struct __exec_nis_args {
int *yp_status;
nss_XbyY_args_t *argp;
} _exec_nis_args;
static int
check_match(nss_XbyY_args_t *argp, int check_policy)
{
execstr_t *exec = (execstr_t *)(argp->returnval);
_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;
if (name && id) {
if ((check_policy && policy &&
(strcmp(policy, exec->policy) != 0)) ||
(type && (strcmp(type, exec->type) != 0))) {
return (0);
}
} else 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 int
check_match_strbuf(nss_XbyY_args_t *argp, char *strbuf, int check_policy)
{
char *last = NULL;
char *sep = KV_TOKEN_DELIMIT;
execstr_t exec;
execstr_t *execp = &exec;
void *sp;
int rc;
if (strbuf[argp->returnlen] == '\n') {
strbuf[argp->returnlen] = '\0';
}
execp->name = _strtok_escape(strbuf, sep, &last);
execp->policy = _strtok_escape(NULL, sep, &last);
execp->type = _strtok_escape(NULL, sep, &last);
execp->res1 = _strtok_escape(NULL, sep, &last);
execp->res2 = _strtok_escape(NULL, sep, &last);
execp->id = _strtok_escape(NULL, sep, &last);
sp = argp->returnval;
argp->returnval = execp;
rc = check_match(argp, check_policy);
argp->returnval = sp;
free(strbuf);
return (rc);
}
static nss_status_t
_exec_nis_parse(const char *instr,
int instr_len,
nss_XbyY_args_t *argp,
int check_policy)
{
int parse_stat;
nss_status_t res;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
char *strbuf;
int check_matched;
argp->returnval = NULL;
argp->returnlen = 0;
parse_stat = (*argp->str2ent)(instr, instr_len, argp->buf.result,
argp->buf.buffer, argp->buf.buflen);
switch (parse_stat) {
case NSS_STR_PARSE_SUCCESS:
argp->returnlen = instr_len;
if (argp->buf.result == NULL) {
argp->returnval = argp->buf.buffer;
if ((strbuf = strdup(instr)) == NULL)
res = NSS_UNAVAIL;
check_matched = check_match_strbuf(argp,
strbuf, check_policy);
} else {
argp->returnval = argp->buf.result;
check_matched = check_match(argp, check_policy);
}
if (check_matched) {
res = NSS_SUCCESS;
if (IS_GET_ALL(_priv_exec->search_flag)) {
if (_doexeclist(argp) == 0) {
res = NSS_UNAVAIL;
}
}
} else {
res = NSS_NOTFOUND;
}
break;
case NSS_STR_PARSE_ERANGE:
argp->erange = 1;
res = NSS_NOTFOUND;
break;
default:
res = NSS_UNAVAIL;
break;
}
return (res);
}
static int
_exec_nis_cb(int instatus,
char *inkey,
int inkeylen,
char *inval,
int invallen,
void *indata)
{
int check_policy = 1;
int stop_cb;
const char *filter;
nss_status_t res;
_exec_nis_args *eargp = (_exec_nis_args *)indata;
nss_XbyY_args_t *argp = eargp->argp;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
if (instatus != YP_TRUE) {
if (instatus != YP_NOMORE) {
*(eargp->yp_status) = YPERR_YPERR;
}
return (0);
}
filter = (_priv_exec->name) ? _priv_exec->name : _priv_exec->id;
inval[invallen] = '\0';
if ((_priv_exec->policy &&
(strstr(inval, _priv_exec->policy) == NULL)) ||
(strstr(inval, filter) == NULL)) {
*(eargp->yp_status) = YPERR_KEY;
return (0);
}
res = _exec_nis_parse(inval, invallen, argp, check_policy);
switch (res) {
case NSS_SUCCESS:
*(eargp->yp_status) = 0;
stop_cb = IS_GET_ONE(_priv_exec->search_flag);
break;
case NSS_UNAVAIL:
*(eargp->yp_status) = YPERR_KEY;
stop_cb = 1;
break;
default:
*(eargp->yp_status) = YPERR_YPERR;
stop_cb = 0;
break;
}
return (stop_cb);
}
static nss_status_t
_exec_nis_lookup(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
{
int ypstatus;
nss_status_t res = NSS_SUCCESS;
nss_status_t ypres;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
if (getby_flag == NSS_DBOP_EXECATTR_BYNAMEID) {
int check_policy = 0;
int vallen;
char *val;
char key[MAX_INPUT];
if (snprintf(key, MAX_INPUT, "%s%s%s%s%s", _priv_exec->name,
KV_TOKEN_DELIMIT, _priv_exec->policy, KV_TOKEN_DELIMIT,
_priv_exec->id) >= MAX_INPUT)
return (NSS_NOTFOUND);
do {
ypres = _nss_nis_ypmatch(be->domain, NIS_MAP_EXECATTR,
key, &val, &vallen, &ypstatus);
if ((check_policy == 0) && (ypstatus == YPERR_KEY)) {
(void) snprintf(key, MAX_INPUT, "%s%s%s",
_priv_exec->name, KV_TOKEN_DELIMIT,
_priv_exec->id);
check_policy = 1;
continue;
} else if (ypres != NSS_SUCCESS) {
res = ypres;
break;
} else {
char *val_save = val;
massage_netdb((const char **)&val, &vallen);
res = _exec_nis_parse((const char *)val,
vallen, argp, check_policy);
free(val_save);
break;
}
} while (res == NSS_SUCCESS);
} else {
int ypstat = YPERR_YPERR;
struct ypall_callback cback;
_exec_nis_args eargs;
eargs.yp_status = &ypstat;
eargs.argp = argp;
cback.foreach = _exec_nis_cb;
cback.data = (void *)&eargs;
ypstatus = __yp_all_cflookup((char *)(be->domain),
(char *)(be->enum_map), &cback, 0);
if (_priv_exec->head_exec != NULL)
return (NSS_SUCCESS);
switch (ypstat) {
case 0:
res = NSS_SUCCESS;
break;
case YPERR_BUSY:
res = NSS_TRYAGAIN;
break;
case YPERR_KEY:
res = NSS_NOTFOUND;
break;
default:
res = NSS_UNAVAIL;
break;
}
}
return (res);
}
static nss_status_t
get_wild(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
{
const char *orig_id;
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 = _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_nis_lookup(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(nis_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYNAME);
_exec_cleanup(res, argp);
return (res);
}
static nss_status_t
getbyid(nis_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_nis_lookup(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(nis_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_nis_lookup(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 nis_backend_op_t execattr_ops[] = {
_nss_nis_destr,
_nss_nis_endent,
_nss_nis_setent,
_nss_nis_getent_netdb,
getbynam,
getbyid,
getbynameid
};
nss_backend_t *
_nss_nis_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_nis_constr(execattr_ops,
sizeof (execattr_ops)/sizeof (execattr_ops[0]),
NIS_MAP_EXECATTR));
}