change getgrent() backends so that a flag (per source) is set once the

source has been exhausted. this allows getgrent() across multiple
sources (e.g, ``group: files nis'') to work correctly. the flags are
reset in setgrent()/endgrent().

(as per similar change in getpwent.c rev 1.42)

XXX: this change means that code that uses getgrent() to obtain a list
of groups will have to do duplicate suppression... getgrouplist()
springs to mind; i'm about to modify that
This commit is contained in:
lukem 1999-04-25 13:39:41 +00:00
parent 21fbe5b6d3
commit 326483c4de

View File

@ -1,4 +1,4 @@
/* $NetBSD: getgrent.c,v 1.35 1999/04/18 02:04:04 lukem Exp $ */
/* $NetBSD: getgrent.c,v 1.36 1999/04/25 13:39:41 lukem Exp $ */
/*
* Copyright (c) 1989, 1993
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94";
#else
__RCSID("$NetBSD: getgrent.c,v 1.35 1999/04/18 02:04:04 lukem Exp $");
__RCSID("$NetBSD: getgrent.c,v 1.36 1999/04/25 13:39:41 lukem Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -87,8 +87,9 @@ __weak_alias(setgroupent,_setgroupent);
static FILE *_gr_fp;
static struct group _gr_group;
static int _gr_stayopen;
static int _gr_nomore;
static int _gr_filesdone;
static void grcleanup __P((void));
static int grscan __P((int, gid_t, const char *));
static int matchline __P((int, gid_t, const char *));
static int start_gr __P((void));
@ -102,10 +103,11 @@ static char line[MAXLINELENGTH];
#ifdef YP
static char *__ypcurrent, *__ypdomain;
static int __ypcurrentlen;
static int _gr_ypdone;
#endif
#ifdef HESIOD
static int __gr_hesnum;
static int _gr_hesnum;
#endif
#ifdef _GROUP_COMPAT
@ -116,9 +118,8 @@ static enum _grmode __grmode;
struct group *
getgrent()
{
_gr_nomore = 0;
if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL) || _gr_nomore)
return(NULL);
if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL))
return (NULL);
return &_gr_group;
}
@ -150,20 +151,28 @@ getgrgid(gid)
return (rval) ? &_gr_group : NULL;
}
static int
start_gr()
void
grcleanup()
{
_gr_filesdone = 0;
#ifdef YP
if (__ypcurrent)
free(__ypcurrent);
__ypcurrent = NULL;
_gr_ypdone = 0;
#endif
#ifdef HESIOD
__gr_hesnum = 0;
_gr_hesnum = 0;
#endif
#ifdef _GROUP_COMPAT
__grmode = GRMODE_NONE;
#endif
}
static int
start_gr()
{
grcleanup();
if (_gr_fp) {
rewind(_gr_fp);
return 1;
@ -190,17 +199,7 @@ setgroupent(stayopen)
void
endgrent()
{
#ifdef YP
if (__ypcurrent)
free(__ypcurrent);
__ypcurrent = NULL;
#endif
#ifdef HESIOD
__gr_hesnum = 0;
#endif
#ifdef _GROUP_COMPAT
__grmode = GRMODE_NONE;
#endif
grcleanup();
if (_gr_fp) {
(void)fclose(_gr_fp);
_gr_fp = NULL;
@ -221,12 +220,12 @@ _local_grscan(rv, cb_data, ap)
gid_t gid = va_arg(ap, gid_t);
const char *name = va_arg(ap, const char *);
if (_gr_filesdone)
return NS_NOTFOUND;
for (;;) {
if (!fgets(line, sizeof(line), _gr_fp)) {
if (!search) {
_gr_nomore = 1;
return NS_SUCCESS;
}
if (!search)
_gr_filesdone = 1;
return NS_NOTFOUND;
}
/* skip lines that are too big */
@ -262,6 +261,8 @@ _dns_grscan(rv, cb_data, ap)
int r;
r = NS_UNAVAIL;
if (!search && _gr_hesnum == -1)
return NS_NOTFOUND;
if (hesiod_init(&context) == -1)
return (r);
@ -273,20 +274,17 @@ _dns_grscan(rv, cb_data, ap)
snprintf(line, sizeof(line), "%u",
(unsigned int)gid);
} else {
snprintf(line, sizeof(line), "group-%u", __gr_hesnum);
__gr_hesnum++;
snprintf(line, sizeof(line), "group-%u", _gr_hesnum);
_gr_hesnum++;
}
line[sizeof(line) - 1] = '\0';
hp = hesiod_resolve(context, line, "group");
if (hp == NULL) {
if (errno == ENOENT) {
if (!search) {
__gr_hesnum = 0;
_gr_nomore = 1;
r = NS_SUCCESS;
} else
r = NS_NOTFOUND;
if (!search)
_gr_hesnum = -1;
r = NS_NOTFOUND;
}
break;
}
@ -369,7 +367,10 @@ _nis_grscan(rv, cb_data, ap)
return NS_NOTFOUND;
}
for (;;) { /* ! search */
/* ! search */
if (_gr_ypdone)
return NS_NOTFOUND;
for (;;) {
data = NULL;
if(__ypcurrent) {
key = NULL;
@ -386,8 +387,8 @@ _nis_grscan(rv, cb_data, ap)
free(key);
if (data)
free(data);
_gr_nomore = 1;
return NS_SUCCESS;
_gr_ypdone = 1;
return NS_NOTFOUND;
default:
if (key)
free(key);