2fe8fb192f
There is important information about booting non-ack images in docs/UPDATING. ack/aout-format images can't be built any more, and booting clang/ELF-format ones is a little different. Updating to the new boot monitor is recommended. Changes in this commit: . drop boot monitor -> allowing dropping ack support . facility to copy ELF boot files to /boot so that old boot monitor can still boot fairly easily, see UPDATING . no more ack-format libraries -> single-case libraries . some cleanup of OBJECT_FMT, COMPILER_TYPE, etc cases . drop several ack toolchain commands, but not all support commands (e.g. aal is gone but acksize is not yet). . a few libc files moved to netbsd libc dir . new /bin/date as minix date used code in libc/ . test compile fix . harmonize includes . /usr/lib is no longer special: without ack, /usr/lib plays no kind of special bootstrapping role any more and bootstrapping is done exclusively through packages, so releases depend even less on the state of the machine making them now. . rename nbsd_lib* to lib* . reduce mtree
991 lines
20 KiB
C
991 lines
20 KiB
C
/* $NetBSD: getnetgrent.c,v 1.41 2009/10/21 01:07:45 snj Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1994 Christos Zoulas
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
#if defined(LIBC_SCCS) && !defined(lint)
|
|
__RCSID("$NetBSD: getnetgrent.c,v 1.41 2009/10/21 01:07:45 snj Exp $");
|
|
#endif /* LIBC_SCCS and not lint */
|
|
|
|
#include "namespace.h"
|
|
#include <sys/types.h>
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <db.h>
|
|
#include <err.h>
|
|
#include <fcntl.h>
|
|
#define _NETGROUP_PRIVATE
|
|
#include <stringlist.h>
|
|
#include <netgroup.h>
|
|
#include <nsswitch.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef YP
|
|
#include <rpc/rpc.h>
|
|
#include <rpcsvc/ypclnt.h>
|
|
#include <rpcsvc/yp_prot.h>
|
|
#endif
|
|
|
|
#ifdef __weak_alias
|
|
__weak_alias(endnetgrent,_endnetgrent)
|
|
__weak_alias(getnetgrent,_getnetgrent)
|
|
__weak_alias(innetgr,_innetgr)
|
|
__weak_alias(setnetgrent,_setnetgrent)
|
|
#endif
|
|
|
|
#define _NG_STAR(s) (((s) == NULL || *(s) == '\0') ? _ngstar : s)
|
|
#define _NG_EMPTY(s) ((s) == NULL ? "" : s)
|
|
#define _NG_ISSPACE(p) (isspace((unsigned char) (p)) || (p) == '\n')
|
|
|
|
static const char _ngstar[] = "*";
|
|
static struct netgroup *_nghead = NULL;
|
|
static struct netgroup *_nglist = NULL;
|
|
static DB *_ng_db;
|
|
|
|
static int getstring(char **, int, __aconst char **);
|
|
static struct netgroup *getnetgroup(char **);
|
|
static int lookup(char *, char **, int);
|
|
static int addgroup(StringList *, char *);
|
|
static int in_check(const char *, const char *, const char *,
|
|
struct netgroup *);
|
|
static int in_find(StringList *, char *, const char *, const char *,
|
|
const char *);
|
|
static char *in_lookup1(const char *, const char *, int);
|
|
static int in_lookup(const char *, const char *, const char *, int);
|
|
|
|
#ifdef NSSRC_FILES
|
|
static const ns_src default_files_nis[] = {
|
|
{ NSSRC_FILES, NS_SUCCESS | NS_NOTFOUND },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, NS_SUCCESS },
|
|
#endif
|
|
{ 0, 0 },
|
|
};
|
|
#endif
|
|
|
|
/*
|
|
* getstring(): Get a string delimited by the character, skipping leading and
|
|
* trailing blanks and advancing the pointer
|
|
*/
|
|
static int
|
|
getstring(char **pp, int del, char __aconst **str)
|
|
{
|
|
size_t len;
|
|
char *sp, *ep, *dp;
|
|
|
|
_DIAGASSERT(pp != NULL);
|
|
_DIAGASSERT(str != NULL);
|
|
|
|
/* skip leading blanks */
|
|
for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
|
|
continue;
|
|
|
|
/* accumulate till delimiter or space */
|
|
for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
|
|
continue;
|
|
|
|
/* hunt for the delimiter */
|
|
for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
|
|
continue;
|
|
|
|
if (*dp != del) {
|
|
*str = NULL;
|
|
return 0;
|
|
}
|
|
|
|
*pp = ++dp;
|
|
|
|
len = (ep - sp) + 1;
|
|
if (len > 1) {
|
|
dp = malloc(len);
|
|
if (dp == NULL)
|
|
return 0;
|
|
(void)memcpy(dp, sp, len);
|
|
dp[len - 1] = '\0';
|
|
} else
|
|
dp = NULL;
|
|
|
|
*str = dp;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* getnetgroup(): Parse a netgroup, and advance the pointer
|
|
*/
|
|
static struct netgroup *
|
|
getnetgroup(pp)
|
|
char **pp;
|
|
{
|
|
struct netgroup *ng;
|
|
|
|
_DIAGASSERT(pp != NULL);
|
|
_DIAGASSERT(*pp != NULL);
|
|
|
|
ng = malloc(sizeof(struct netgroup));
|
|
if (ng == NULL)
|
|
return NULL;
|
|
|
|
(*pp)++; /* skip '(' */
|
|
if (!getstring(pp, ',', &ng->ng_host))
|
|
goto badhost;
|
|
|
|
if (!getstring(pp, ',', &ng->ng_user))
|
|
goto baduser;
|
|
|
|
if (!getstring(pp, ')', &ng->ng_domain))
|
|
goto baddomain;
|
|
|
|
#ifdef DEBUG_NG
|
|
{
|
|
char buf[1024];
|
|
(void) fprintf(stderr, "netgroup %s\n",
|
|
_ng_print(buf, sizeof(buf), ng));
|
|
}
|
|
#endif
|
|
return ng;
|
|
|
|
baddomain:
|
|
if (ng->ng_user)
|
|
free(ng->ng_user);
|
|
baduser:
|
|
if (ng->ng_host)
|
|
free(ng->ng_host);
|
|
badhost:
|
|
free(ng);
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
_ng_cycle(const char *grp, const StringList *sl)
|
|
{
|
|
size_t i;
|
|
warnx("netgroup: Cycle in group `%s'", grp);
|
|
(void)fprintf(stderr, "groups: ");
|
|
for (i = 0; i < sl->sl_cur; i++)
|
|
(void)fprintf(stderr, "%s ", sl->sl_str[i]);
|
|
(void)fprintf(stderr, "\n");
|
|
}
|
|
|
|
static int _local_lookup(void *, void *, va_list);
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_local_lookup(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
char *name = va_arg(ap, char *);
|
|
char **line = va_arg(ap, char **);
|
|
int bywhat = va_arg(ap, int);
|
|
|
|
DBT key, data;
|
|
size_t len;
|
|
char *ks;
|
|
int r;
|
|
|
|
if (_ng_db == NULL)
|
|
return NS_UNAVAIL;
|
|
|
|
len = strlen(name) + 2;
|
|
ks = malloc(len);
|
|
if (ks == NULL)
|
|
return NS_UNAVAIL;
|
|
|
|
ks[0] = bywhat;
|
|
(void)memcpy(&ks[1], name, len - 1);
|
|
|
|
key.data = (u_char *)ks;
|
|
key.size = len;
|
|
|
|
r = (*_ng_db->get)(_ng_db, &key, &data, 0);
|
|
free(ks);
|
|
switch (r) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
return NS_NOTFOUND;
|
|
case -1:
|
|
/* XXX: call endnetgrent() here ? */
|
|
return NS_UNAVAIL;
|
|
}
|
|
|
|
*line = strdup(data.data);
|
|
if (*line == NULL)
|
|
return NS_UNAVAIL;
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
#ifdef YP
|
|
static int _nis_lookup(void *, void *, va_list);
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_nis_lookup(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
char *name = va_arg(ap, char *);
|
|
char **line = va_arg(ap, char **);
|
|
int bywhat = va_arg(ap, int);
|
|
|
|
static char *__ypdomain;
|
|
int i;
|
|
const char *map = NULL;
|
|
|
|
if(__ypdomain == NULL) {
|
|
switch (yp_get_default_domain(&__ypdomain)) {
|
|
case 0:
|
|
break;
|
|
case YPERR_RESRC:
|
|
return NS_TRYAGAIN;
|
|
default:
|
|
return NS_UNAVAIL;
|
|
}
|
|
}
|
|
|
|
switch (bywhat) {
|
|
case _NG_KEYBYNAME:
|
|
map = "netgroup";
|
|
break;
|
|
|
|
case _NG_KEYBYUSER:
|
|
map = "netgroup.byuser";
|
|
break;
|
|
|
|
case _NG_KEYBYHOST:
|
|
map = "netgroup.byhost";
|
|
break;
|
|
|
|
default:
|
|
abort();
|
|
}
|
|
|
|
*line = NULL;
|
|
switch (yp_match(__ypdomain, map, name, (int)strlen(name), line, &i)) {
|
|
case 0:
|
|
return NS_SUCCESS;
|
|
case YPERR_KEY:
|
|
if (*line)
|
|
free(*line);
|
|
return NS_NOTFOUND;
|
|
default:
|
|
if (*line)
|
|
free(*line);
|
|
return NS_UNAVAIL;
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
#endif
|
|
|
|
#ifdef NSSRC_FILES
|
|
/*
|
|
* lookup(): Find the given key in the database or yp, and return its value
|
|
* in *line; returns 1 if key was found, 0 otherwise
|
|
*/
|
|
static int
|
|
lookup(char *name, char **line, int bywhat)
|
|
{
|
|
int r;
|
|
static const ns_dtab dtab[] = {
|
|
NS_FILES_CB(_local_lookup, NULL)
|
|
NS_NIS_CB(_nis_lookup, NULL)
|
|
NS_NULL_CB
|
|
};
|
|
|
|
_DIAGASSERT(name != NULL);
|
|
_DIAGASSERT(line != NULL);
|
|
|
|
r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "lookup", default_files_nis,
|
|
name, line, bywhat);
|
|
return (r == NS_SUCCESS) ? 1 : 0;
|
|
}
|
|
#else
|
|
static int
|
|
_local_lookupv(int *rv, void *cbdata, ...)
|
|
{
|
|
int e;
|
|
va_list ap;
|
|
va_start(ap, cbdata);
|
|
e = _local_lookup(rv, cbdata, ap);
|
|
va_end(ap);
|
|
return e;
|
|
}
|
|
|
|
static int
|
|
lookup(name, line, bywhat)
|
|
char *name;
|
|
char **line;
|
|
int bywhat;
|
|
{
|
|
return _local_lookupv(NULL, NULL, name, line, bywhat) == NS_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
|
|
* line was empty or a comment _NG_GROUP: line had a netgroup definition,
|
|
* returned in ng _NG_NAME: line had a netgroup name, returned in name
|
|
*
|
|
* Public since used by netgroup_mkdb
|
|
*/
|
|
int
|
|
_ng_parse(char **p, char **name, struct netgroup **ng)
|
|
{
|
|
|
|
_DIAGASSERT(p != NULL);
|
|
_DIAGASSERT(*p != NULL);
|
|
_DIAGASSERT(name != NULL);
|
|
_DIAGASSERT(ng != NULL);
|
|
|
|
while (**p) {
|
|
if (**p == '#')
|
|
/* comment */
|
|
return _NG_NONE;
|
|
|
|
while (**p && _NG_ISSPACE(**p))
|
|
/* skipblank */
|
|
(*p)++;
|
|
|
|
if (**p == '(') {
|
|
if ((*ng = getnetgroup(p)) == NULL)
|
|
return _NG_ERROR;
|
|
return _NG_GROUP;
|
|
} else {
|
|
char *np;
|
|
size_t i;
|
|
|
|
for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++)
|
|
continue;
|
|
if (np != *p) {
|
|
i = (*p - np) + 1;
|
|
*name = malloc(i);
|
|
if (*name == NULL)
|
|
return _NG_ERROR;
|
|
(void)memcpy(*name, np, i);
|
|
(*name)[i - 1] = '\0';
|
|
return _NG_NAME;
|
|
}
|
|
}
|
|
}
|
|
return _NG_NONE;
|
|
}
|
|
|
|
|
|
/*
|
|
* addgroup(): Recursively add all the members of the netgroup to this group.
|
|
* returns 0 upon failure, nonzero upon success.
|
|
* grp is not a valid pointer after return (either free(3)ed or allocated
|
|
* to a stringlist). in either case, it shouldn't be used again.
|
|
*/
|
|
static int
|
|
addgroup(StringList *sl, char *grp)
|
|
{
|
|
char *line, *p;
|
|
struct netgroup *ng;
|
|
char *name;
|
|
|
|
_DIAGASSERT(sl != NULL);
|
|
_DIAGASSERT(grp != NULL);
|
|
|
|
#ifdef DEBUG_NG
|
|
(void)fprintf(stderr, "addgroup(%s)\n", grp);
|
|
#endif
|
|
/* check for cycles */
|
|
if (sl_find(sl, grp) != NULL) {
|
|
_ng_cycle(grp, sl);
|
|
free(grp);
|
|
return 0;
|
|
}
|
|
if (sl_add(sl, grp) == -1) {
|
|
free(grp);
|
|
return 0;
|
|
}
|
|
|
|
/* Lookup this netgroup */
|
|
line = NULL;
|
|
if (!lookup(grp, &line, _NG_KEYBYNAME)) {
|
|
if (line)
|
|
free(line);
|
|
return 0;
|
|
}
|
|
|
|
p = line;
|
|
|
|
for (;;) {
|
|
switch (_ng_parse(&p, &name, &ng)) {
|
|
case _NG_NONE:
|
|
/* Done with the line */
|
|
free(line);
|
|
return 1;
|
|
|
|
case _NG_GROUP:
|
|
/* new netgroup */
|
|
/* add to the list */
|
|
ng->ng_next = _nglist;
|
|
_nglist = ng;
|
|
break;
|
|
|
|
case _NG_NAME:
|
|
/* netgroup name */
|
|
if (!addgroup(sl, name))
|
|
return 0;
|
|
break;
|
|
|
|
case _NG_ERROR:
|
|
return 0;
|
|
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* in_check(): Compare the spec with the netgroup
|
|
*/
|
|
static int
|
|
in_check(const char *host, const char *user, const char *domain,
|
|
struct netgroup *ng)
|
|
{
|
|
|
|
/* host may be NULL */
|
|
/* user may be NULL */
|
|
/* domain may be NULL */
|
|
_DIAGASSERT(ng != NULL);
|
|
|
|
if ((host != NULL) && (ng->ng_host != NULL)
|
|
&& strcmp(ng->ng_host, host) != 0)
|
|
return 0;
|
|
|
|
if ((user != NULL) && (ng->ng_user != NULL)
|
|
&& strcmp(ng->ng_user, user) != 0)
|
|
return 0;
|
|
|
|
if ((domain != NULL) && (ng->ng_domain != NULL)
|
|
&& strcmp(ng->ng_domain, domain) != 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* in_find(): Find a match for the host, user, domain spec.
|
|
* grp is not a valid pointer after return (either free(3)ed or allocated
|
|
* to a stringlist). in either case, it shouldn't be used again.
|
|
*/
|
|
static int
|
|
in_find(StringList *sl, char *grp, const char *host, const char *user,
|
|
const char *domain)
|
|
{
|
|
char *line, *p;
|
|
int i;
|
|
struct netgroup *ng;
|
|
char *name;
|
|
|
|
_DIAGASSERT(sl != NULL);
|
|
_DIAGASSERT(grp != NULL);
|
|
/* host may be NULL */
|
|
/* user may be NULL */
|
|
/* domain may be NULL */
|
|
|
|
#ifdef DEBUG_NG
|
|
(void)fprintf(stderr, "in_find(%s)\n", grp);
|
|
#endif
|
|
/* check for cycles */
|
|
if (sl_find(sl, grp) != NULL) {
|
|
_ng_cycle(grp, sl);
|
|
free(grp);
|
|
return 0;
|
|
}
|
|
if (sl_add(sl, grp) == -1) {
|
|
free(grp);
|
|
return 0;
|
|
}
|
|
|
|
/* Lookup this netgroup */
|
|
line = NULL;
|
|
if (!lookup(grp, &line, _NG_KEYBYNAME)) {
|
|
if (line)
|
|
free(line);
|
|
return 0;
|
|
}
|
|
|
|
p = line;
|
|
|
|
for (;;) {
|
|
switch (_ng_parse(&p, &name, &ng)) {
|
|
case _NG_NONE:
|
|
/* Done with the line */
|
|
free(line);
|
|
return 0;
|
|
|
|
case _NG_GROUP:
|
|
/* new netgroup */
|
|
i = in_check(host, user, domain, ng);
|
|
if (ng->ng_host != NULL)
|
|
free(ng->ng_host);
|
|
if (ng->ng_user != NULL)
|
|
free(ng->ng_user);
|
|
if (ng->ng_domain != NULL)
|
|
free(ng->ng_domain);
|
|
free(ng);
|
|
if (i) {
|
|
free(line);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case _NG_NAME:
|
|
/* netgroup name */
|
|
if (in_find(sl, name, host, user, domain)) {
|
|
free(line);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case _NG_ERROR:
|
|
free(line);
|
|
return 0;
|
|
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* _ng_makekey(): Make a key from the two names given. The key is of the form
|
|
* <name1>.<name2> Names strings are replaced with * if they are empty;
|
|
* Returns NULL if there's a problem.
|
|
*/
|
|
char *
|
|
_ng_makekey(const char *s1, const char *s2, size_t len)
|
|
{
|
|
char *buf;
|
|
|
|
/* s1 may be NULL */
|
|
/* s2 may be NULL */
|
|
|
|
buf = malloc(len);
|
|
if (buf != NULL)
|
|
(void)snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2));
|
|
return buf;
|
|
}
|
|
|
|
void
|
|
_ng_print(char *buf, size_t len, const struct netgroup *ng)
|
|
{
|
|
_DIAGASSERT(buf != NULL);
|
|
_DIAGASSERT(ng != NULL);
|
|
|
|
(void)snprintf(buf, len, "(%s,%s,%s)", _NG_EMPTY(ng->ng_host),
|
|
_NG_EMPTY(ng->ng_user), _NG_EMPTY(ng->ng_domain));
|
|
}
|
|
|
|
|
|
/*
|
|
* in_lookup1(): Fast lookup for a key in the appropriate map
|
|
*/
|
|
static char *
|
|
in_lookup1(const char *key, const char *domain, int map)
|
|
{
|
|
char *line;
|
|
size_t len;
|
|
char *ptr;
|
|
int res;
|
|
|
|
/* key may be NULL */
|
|
/* domain may be NULL */
|
|
|
|
len = (key ? strlen(key) : 1) + (domain ? strlen(domain) : 1) + 2;
|
|
ptr = _ng_makekey(key, domain, len);
|
|
if (ptr == NULL)
|
|
return NULL;
|
|
res = lookup(ptr, &line, map);
|
|
free(ptr);
|
|
return res ? line : NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* in_lookup(): Fast lookup for a key in the appropriate map
|
|
*/
|
|
static int
|
|
in_lookup(const char *group, const char *key, const char *domain, int map)
|
|
{
|
|
size_t len;
|
|
char *ptr, *line;
|
|
|
|
_DIAGASSERT(group != NULL);
|
|
/* key may be NULL */
|
|
/* domain may be NULL */
|
|
|
|
if (domain != NULL) {
|
|
/* Domain specified; look in "group.domain" and "*.domain" */
|
|
if ((line = in_lookup1(key, domain, map)) == NULL)
|
|
line = in_lookup1(NULL, domain, map);
|
|
} else
|
|
line = NULL;
|
|
|
|
if (line == NULL) {
|
|
/*
|
|
* domain not specified or domain lookup failed; look in
|
|
* "group.*" and "*.*"
|
|
*/
|
|
if (((line = in_lookup1(key, NULL, map)) == NULL) &&
|
|
((line = in_lookup1(NULL, NULL, map)) == NULL))
|
|
return 0;
|
|
}
|
|
|
|
len = strlen(group);
|
|
|
|
for (ptr = line; (ptr = strstr(ptr, group)) != NULL;)
|
|
/* Make sure we did not find a substring */
|
|
if ((ptr != line && ptr[-1] != ',') ||
|
|
(ptr[len] != '\0' && strchr("\n\t ,", ptr[len]) == NULL))
|
|
ptr++;
|
|
else {
|
|
free(line);
|
|
return 1;
|
|
}
|
|
|
|
free(line);
|
|
return 0;
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_local_endnetgrent(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
for (_nglist = _nghead; _nglist != NULL; _nglist = _nghead) {
|
|
_nghead = _nglist->ng_next;
|
|
if (_nglist->ng_host != NULL)
|
|
free(_nglist->ng_host);
|
|
if (_nglist->ng_user != NULL)
|
|
free(_nglist->ng_user);
|
|
if (_nglist->ng_domain != NULL)
|
|
free(_nglist->ng_domain);
|
|
free(_nglist);
|
|
}
|
|
|
|
if (_ng_db) {
|
|
(void)(*_ng_db->close)(_ng_db);
|
|
_ng_db = NULL;
|
|
}
|
|
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_local_setnetgrent(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
const char *ng = va_arg(ap, const char *);
|
|
StringList *sl;
|
|
char *ng_copy;
|
|
|
|
_DIAGASSERT(ng != NULL);
|
|
|
|
sl = sl_init();
|
|
if (sl == NULL)
|
|
return NS_TRYAGAIN;
|
|
|
|
/* Cleanup any previous storage */
|
|
if (_nghead != NULL)
|
|
endnetgrent();
|
|
|
|
if (_ng_db == NULL)
|
|
_ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
|
|
|
|
ng_copy = strdup(ng);
|
|
if (ng_copy != NULL)
|
|
addgroup(sl, ng_copy);
|
|
_nghead = _nglist;
|
|
sl_free(sl, 1);
|
|
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_local_getnetgrent(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
int *retval = va_arg(ap, int *);
|
|
const char **host = va_arg(ap, const char **);
|
|
const char **user = va_arg(ap, const char **);
|
|
const char **domain = va_arg(ap, const char **);
|
|
|
|
_DIAGASSERT(host != NULL);
|
|
_DIAGASSERT(user != NULL);
|
|
_DIAGASSERT(domain != NULL);
|
|
|
|
*retval = 0;
|
|
|
|
if (_nglist == NULL)
|
|
return NS_TRYAGAIN;
|
|
|
|
*host = _nglist->ng_host;
|
|
*user = _nglist->ng_user;
|
|
*domain = _nglist->ng_domain;
|
|
|
|
_nglist = _nglist->ng_next;
|
|
|
|
*retval = 1;
|
|
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_local_innetgr(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
int *retval = va_arg(ap, int *);
|
|
const char *grp = va_arg(ap, const char *);
|
|
const char *host = va_arg(ap, const char *);
|
|
const char *user = va_arg(ap, const char *);
|
|
const char *domain = va_arg(ap, const char *);
|
|
|
|
int found;
|
|
StringList *sl;
|
|
char *grcpy;
|
|
|
|
_DIAGASSERT(grp != NULL);
|
|
/* host may be NULL */
|
|
/* user may be NULL */
|
|
/* domain may be NULL */
|
|
|
|
if (_ng_db == NULL)
|
|
_ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
|
|
|
|
/* Try the fast lookup first */
|
|
if (host != NULL && user == NULL) {
|
|
if (in_lookup(grp, host, domain, _NG_KEYBYHOST)) {
|
|
*retval = 1;
|
|
return NS_SUCCESS;
|
|
}
|
|
} else if (host == NULL && user != NULL) {
|
|
if (in_lookup(grp, user, domain, _NG_KEYBYUSER)) {
|
|
*retval = 1;
|
|
return NS_SUCCESS;
|
|
}
|
|
}
|
|
/* If a domainname is given, we would have found a match */
|
|
if (domain != NULL) {
|
|
*retval = 0;
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
/* Too bad need the slow recursive way */
|
|
sl = sl_init();
|
|
if (sl == NULL) {
|
|
*retval = 0;
|
|
return NS_SUCCESS;
|
|
}
|
|
if ((grcpy = strdup(grp)) == NULL) {
|
|
sl_free(sl, 1);
|
|
*retval = 0;
|
|
return NS_SUCCESS;
|
|
}
|
|
found = in_find(sl, grcpy, host, user, domain);
|
|
sl_free(sl, 1);
|
|
|
|
*retval = found;
|
|
return NS_SUCCESS;
|
|
}
|
|
|
|
#ifdef YP
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_nis_endnetgrent(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
return _local_endnetgrent(rv, cb_data, ap);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_nis_setnetgrent(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
return _local_setnetgrent(rv, cb_data, ap);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_nis_getnetgrent(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
return _local_getnetgrent(rv, cb_data, ap);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static int
|
|
_nis_innetgr(void *rv, void *cb_data, va_list ap)
|
|
{
|
|
return _local_innetgr(rv, cb_data, ap);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef NSSRC_FILES
|
|
void
|
|
endnetgrent(void)
|
|
{
|
|
static const ns_dtab dtab[] = {
|
|
NS_FILES_CB(_local_endnetgrent, NULL)
|
|
NS_NIS_CB(_nis_endnetgrent, NULL)
|
|
NS_NULL_CB
|
|
};
|
|
|
|
(void) nsdispatch(NULL, dtab, NSDB_NETGROUP, "endnetgrent",
|
|
__nsdefaultcompat);
|
|
}
|
|
#else
|
|
static int
|
|
_local_endnetgrentv(int *rv, void *cbdata, ...)
|
|
{
|
|
int e;
|
|
va_list ap;
|
|
va_start(ap, cbdata);
|
|
e = _local_endnetgrent(rv, cbdata, ap);
|
|
va_end(ap);
|
|
return e;
|
|
}
|
|
|
|
void
|
|
endnetgrent(void)
|
|
{
|
|
(void)_local_endnetgrentv(NULL, NULL, NULL);
|
|
}
|
|
#endif
|
|
|
|
#ifdef NSSRC_FILES
|
|
void
|
|
setnetgrent(const char *ng)
|
|
{
|
|
static const ns_dtab dtab[] = {
|
|
NS_FILES_CB(_local_setnetgrent, NULL)
|
|
NS_NIS_CB(_nis_setnetgrent, NULL)
|
|
NS_NULL_CB
|
|
};
|
|
|
|
(void) nsdispatch(NULL, dtab, NSDB_NETGROUP, "setnetgrent",
|
|
__nsdefaultnis, ng);
|
|
}
|
|
#else
|
|
static int
|
|
_local_setnetgrentv(int *rv, void *cbdata, ...)
|
|
{
|
|
int e;
|
|
va_list ap;
|
|
va_start(ap, cbdata);
|
|
e = _local_setnetgrent(rv, cbdata, ap);
|
|
va_end(ap);
|
|
return e;
|
|
}
|
|
|
|
void
|
|
setnetgrent(const char *ng)
|
|
{
|
|
(void) _local_setnetgrentv(NULL, NULL,ng);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef NSSRC_FILES
|
|
int
|
|
getnetgrent(const char **host, const char **user, const char **domain)
|
|
{
|
|
int r, retval;
|
|
static const ns_dtab dtab[] = {
|
|
NS_FILES_CB(_local_getnetgrent, NULL)
|
|
NS_NIS_CB(_nis_getnetgrent, NULL)
|
|
NS_NULL_CB
|
|
};
|
|
|
|
r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "getnetgrent",
|
|
__nsdefaultnis, &retval, host, user, domain);
|
|
|
|
return (r == NS_SUCCESS) ? retval : 0;
|
|
}
|
|
#else
|
|
static int
|
|
_local_getnetgrentv(int *rv, void *cbdata, ...)
|
|
{
|
|
int e;
|
|
va_list ap;
|
|
va_start(ap, cbdata);
|
|
e = _local_getnetgrent(rv, cbdata, ap);
|
|
va_end(ap);
|
|
return e;
|
|
}
|
|
|
|
int
|
|
getnetgrent(const char **host, const char **user, const char **domain)
|
|
{
|
|
return _local_getnetgrentv(NULL, NULL, host, user, domain) == NS_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
#ifdef NSSRC_FILES
|
|
int
|
|
innetgr(const char *grp, const char *host, const char *user,
|
|
const char *domain)
|
|
{
|
|
int r, retval;
|
|
static const ns_dtab dtab[] = {
|
|
NS_FILES_CB(_local_innetgr, NULL)
|
|
NS_NIS_CB(_nis_innetgr, NULL)
|
|
NS_NULL_CB
|
|
};
|
|
|
|
r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "innetgr",
|
|
__nsdefaultnis, &retval, grp, host, user, domain);
|
|
|
|
return (r == NS_SUCCESS) ? retval : 0;
|
|
}
|
|
#else
|
|
static int
|
|
_local_innetgrv(int *rv, void *cbdata, ...)
|
|
{
|
|
int e;
|
|
va_list ap;
|
|
va_start(ap, cbdata);
|
|
e = _local_innetgr(rv, cbdata, ap);
|
|
va_end(ap);
|
|
return e;
|
|
}
|
|
|
|
int
|
|
innetgr(const char *grp, const char *host, const char *user,
|
|
const char *domain)
|
|
{
|
|
return _local_innetgrv(NULL, NULL, grp, host, user, domain) == NS_SUCCESS;
|
|
}
|
|
#endif
|