diff --git a/libexec/revnetgroup/Makefile b/libexec/revnetgroup/Makefile new file mode 100644 index 000000000000..dec0e7b8e653 --- /dev/null +++ b/libexec/revnetgroup/Makefile @@ -0,0 +1,8 @@ +# $Id$ + +PROG= revnetgroup +SRCS= revnetgroup.c hash.c parse_netgroup.c + +MAN8= revnetgroup.8 + +.include diff --git a/libexec/revnetgroup/hash.c b/libexec/revnetgroup/hash.c new file mode 100644 index 000000000000..b8758439e9e4 --- /dev/null +++ b/libexec/revnetgroup/hash.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1995 + * Bill Paul . 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR CONTRIBUTORS 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. + * + * $Id$ + */ + +#include +#include +#include +#include +#include "hash.h" + +/* + * This hash function is stolen directly from the + * Berkeley DB package. It already exists inside libc, but + * it's declared static which prevents us from calling it + * from here. + */ +/* + * OZ's original sdbm hash + */ +u_int32_t +hash(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register size_t loop; + register u_int32_t h; + +#define HASHC h = *key++ + 65599 * h + + h = 0; + key = keyarg; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { + HASHC; + /* FALLTHROUGH */ + case 7: + HASHC; + /* FALLTHROUGH */ + case 6: + HASHC; + /* FALLTHROUGH */ + case 5: + HASHC; + /* FALLTHROUGH */ + case 4: + HASHC; + /* FALLTHROUGH */ + case 3: + HASHC; + /* FALLTHROUGH */ + case 2: + HASHC; + /* FALLTHROUGH */ + case 1: + HASHC; + } while (--loop); + } + } + return (h); +} + +/* + * Generate a hash value for a given key (character string). + * We mask off all but the lower 8 bits since our table array + * can only hole 256 elements. + */ +u_int32_t hashkey(key) + char *key; +{ + + if (key == NULL) + return (-1); + return(hash((void *)key, strlen(key)) & HASH_MASK); +} + +/* Find an entry in the hash table (may be hanging off a linked list). */ +char *lookup(table, key) + struct group_entry *table[]; + char *key; +{ + struct group_entry *cur; + + cur = table[hashkey(key)]; + + while (cur) { + if (!strcmp(cur->key, key)) + return(cur->data); + cur = cur->next; + } + + return(NULL); +} + +/* + * Store an entry in the main netgroup hash table. Here's how this + * works: the table can only be so big when we initialize it (TABLESIZE) + * but the number of netgroups in the /etc/netgroup file could easily be + * much larger than the table. Since our hash values are adjusted to + * never be greater than TABLESIZE too, this means it won't be long before + * we find ourselves with two keys that hash to the same value. + * + * One way to deal with this is to malloc(2) a second table and start + * doing indirection, but this is a pain in the butt and it's not worth + * going to all that trouble for a dinky littke program like this. Instead, + * we turn each table entry into a linked list and simply link keys + * with the same hash value together at the same index location within + * the table. + * + * That's a lot of comment for such a small piece of code, isn't it. + */ +void store (table, key, data) + struct group_entry *table[]; + char *key, *data; +{ + struct group_entry *new; + u_int32_t i; + + i = hashkey(key); + + new = (struct group_entry *)malloc(sizeof(struct group_entry)); + new->key = strdup(key); + new->data = strdup(data); + new->next = table[i]; + table[i] = new; + + return; +} + +/* + * Store an group member entry and/or update its grouplist. This is + * a bit more complicated than the previous function since we have to + * maintain not only the hash table of group members, each group member + * structure also has a linked list of groups hung off it. If handed + * a member name that we haven't encountered before, we have to do + * two things: add that member to the table (possibly hanging them + * off the end of a linked list, as above), and add a group name to + * the member's grouplist list. If we're handed a name that already has + * an entry in the table, then we just have to do one thing, which is + * to update its grouplist. + */ +void mstore (table, key, data, domain) + struct member_entry *table[]; + char *key, *data, *domain; +{ + struct member_entry *cur, *new; + struct grouplist *tmp; + u_int32_t i; + + i = hashkey(key); + cur = table[i]; + + tmp = (struct grouplist *)malloc(sizeof(struct grouplist)); + tmp->groupname = strdup(data); + tmp->next = NULL; + + /* Check if all we have to do is insert a new groupname. */ + while (cur) { + if (!strcmp(cur->key, key)) { + tmp->next = cur->groups; + cur->groups = tmp; + return; + } + cur = cur->next; + } + + /* Didn't find a match -- add the whole mess to the table. */ + new = (struct member_entry *)malloc(sizeof(struct member_entry)); + new->key = strdup(key); + new->domain = domain ? strdup(domain) : "*"; + new->groups = tmp; + new->next = table[i]; + table[i] = new; + + return; +} diff --git a/libexec/revnetgroup/hash.h b/libexec/revnetgroup/hash.h new file mode 100644 index 000000000000..2212534ff3c9 --- /dev/null +++ b/libexec/revnetgroup/hash.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1995 + * Bill Paul . 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR CONTRIBUTORS 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. + * + * $Id$ + */ + +/* Groupname entry hung off a member_entry node. */ +struct grouplist { + char *groupname; + struct grouplist *next; +}; + +/* Entry in the cooked member list hash table. */ +struct member_entry { + char *key; + char *domain; + struct grouplist *groups; + struct member_entry *next; +}; + +/* Entry in the raw netgroup table. */ +struct group_entry { + char *key; + char *data; + struct grps *groups; + struct group_entry *next; +}; + +/* Table size (chosen arbitrarily). Not too big, not too small. */ +#define TABLESIZE 256 +#define HASH_MASK 0x000000FF diff --git a/libexec/revnetgroup/parse_netgroup.c b/libexec/revnetgroup/parse_netgroup.c new file mode 100644 index 000000000000..99dfaeb37b61 --- /dev/null +++ b/libexec/revnetgroup/parse_netgroup.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +/* + * This is a specially hacked-up version of getnetgrent.c used to parse + * data from the stored hash table of netgroup info rather than from a + * file. It's used mainly for the parse_netgroup() function. All the YP + * stuff and file support has been stripped out since it isn't needed. + */ + +#include +#include +#include +#include +#include "hash.h" + +/* + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * __endnetgrent(). + * There are two linked lists: + * - linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * - netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /* Chain ptr. */ + int l_parsed; /* Flag for cycles */ + char *l_groupname; /* Name of netgroup */ + char *l_line; /* Netgroup entrie(s) to be parsed */ +}; + +struct netgrp { + struct netgrp *ng_next; /* Chain ptr */ + char *ng_str[3]; /* Field pointers, see below */ +}; +#define NG_HOST 0 /* Host name */ +#define NG_USER 1 /* User name */ +#define NG_DOM 2 /* and Domain name */ + +static struct linelist *linehead = (struct linelist *)0; +static struct netgrp *nextgrp = (struct netgrp *)0; +static struct { + struct netgrp *gr; + char *grname; +} grouphead = { + (struct netgrp *)0, + (char *)0, +}; +static int parse_netgrp(); +static struct linelist *read_for_group(); +void __setnetgrent(), __endnetgrent(); +int __getnetgrent(); +extern struct group_entry *gtable[]; +extern char *lookup __P(( struct group_entry *[], char * )); +#define LINSIZ 1024 /* Length of netgroup file line */ + +/* + * setnetgrent() + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +void +__setnetgrent(group) + char *group; +{ + /* Sanity check */ + + if (group == NULL || !strlen(group)) + return; + + if (grouphead.gr == (struct netgrp *)0 || + strcmp(group, grouphead.grname)) { + __endnetgrent(); + if (parse_netgrp(group)) + __endnetgrent(); + else { + grouphead.grname = (char *) + malloc(strlen(group) + 1); + strcpy(grouphead.grname, group); + } + } + nextgrp = grouphead.gr; +} + +/* + * Get the next netgroup off the list. + */ +int +__getnetgrent(hostp, userp, domp) + char **hostp, **userp, **domp; +{ + if (nextgrp) { + *hostp = nextgrp->ng_str[NG_HOST]; + *userp = nextgrp->ng_str[NG_USER]; + *domp = nextgrp->ng_str[NG_DOM]; + nextgrp = nextgrp->ng_next; + return (1); + } + return (0); +} + +/* + * __endnetgrent() - cleanup + */ +void +__endnetgrent() +{ + register struct linelist *lp, *olp; + register struct netgrp *gp, *ogp; + + lp = linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + linehead = (struct linelist *)0; + if (grouphead.grname) { + free(grouphead.grname); + grouphead.grname = (char *)0; + } + gp = grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + grouphead.gr = (struct netgrp *)0; +} + +/* + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(group) + char *group; +{ + register char *spos, *epos; + register int len, strpos; +#ifdef DEBUG + register int fields; +#endif + char *pos, *gpos; + struct netgrp *grp; + struct linelist *lp = linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == (struct linelist *)0 && + (lp = read_for_group(group)) == (struct linelist *)0) + return (1); + if (lp->l_parsed) { +#ifdef DEBUG + /* + * This error message is largely superflous since the + * code handles the error condition sucessfully, and + * spewing it out from inside libc can actually hose + * certain programs. + */ + fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); +#endif + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + /* Watch for null pointer dereferences, dammit! */ + while (pos != NULL && *pos != '\0') { + if (*pos == '(') { + grp = (struct netgrp *)malloc(sizeof (struct netgrp)); + bzero((char *)grp, sizeof (struct netgrp)); + grp->ng_next = grouphead.gr; + grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); +#ifdef DEBUG + fields = 0; +#endif + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { +#ifdef DEBUG + fields++; +#endif + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + grp->ng_str[strpos] = (char *) + malloc(len + 1); + bcopy(spos, grp->ng_str[strpos], + len + 1); + } + } else { + /* + * All other systems I've tested + * return NULL for empty netgroup + * fields. It's up to user programs + * to handle the NULLs appropriately. + */ + grp->ng_str[strpos] = NULL; + } + } +#ifdef DEBUG + /* + * Note: on other platforms, malformed netgroup + * entries are not normally flagged. While we + * can catch bad entries and report them, we should + * stay silent by default for compatibility's sake. + */ + if (fields < 3) + fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", + grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], + grp->ng_str[NG_USER] == NULL ? "" : ",", + grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], + grp->ng_str[NG_DOM] == NULL ? "" : ",", + grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], + lp->l_groupname); +#endif + } else { + spos = strsep(&pos, ", \t"); + if (parse_netgrp(spos)) + continue; + } + /* Watch for null pointer dereferences, dammit! */ + if (pos != NULL) + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); +} + +/* + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(group) + char *group; +{ + register char *pos, *spos, *linep, *olinep; + register int len, olen; + int cont; + struct linelist *lp; + char line[LINSIZ + 1]; + char *key = NULL, *data = NULL; + + data = lookup (gtable, group); + sprintf(line, "%s %s", group, data); + pos = (char *)&line; +#ifdef CANT_HAPPEN + if (*pos == '#') + continue; +#endif + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + lp = (struct linelist *)malloc(sizeof (*lp)); + lp->l_parsed = 0; + lp->l_groupname = (char *)malloc(len + 1); + bcopy(spos, lp->l_groupname, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + linep = (char *)malloc(olen + len + 1); + if (olen > 0) { + bcopy(olinep, linep, olen); + free(olinep); + } + bcopy(pos, linep + olen, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } +#ifdef CANT_HAPPEN + if (cont) { + if (fgets(line, LINSIZ, netf)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } +#endif + } while (cont); + lp->l_line = linep; + lp->l_next = linehead; + linehead = lp; +#ifdef CANT_HAPPEN + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) +#endif + return (lp); + } + return ((struct linelist *)0); +} diff --git a/libexec/revnetgroup/revnetgroup.8 b/libexec/revnetgroup/revnetgroup.8 new file mode 100644 index 000000000000..0a1330efc739 --- /dev/null +++ b/libexec/revnetgroup/revnetgroup.8 @@ -0,0 +1,137 @@ +.\" Copyright (c) 1995 +.\" Bill Paul . 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Bill Paul. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR CONTRIBUTORS 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. +.\" +.\" $Id$ +.\" +.Dd October 24, 1995 +.Dt REVNETGROUP 8 +.Os +.Sh NAME +.Nm revnetgroup +.Nd "generate reverse netgroup data" +.Sh SYNOPSIS +.Nm revnetgroup +.Fl u +.Fl h +.Op Fl f Ar netgroup_file +.Sh DESCRIPTION +.Nm revnetgroup +processes the contents of a file in +.Xr netgroup 5 +format into what is called +.Pa reverse netgroup +form. That is, where the original file shows +netgroup memberships in terms of which members reside in a particular +group, the reverse netgroup format specifies what groups are associated +with a particular member. This information is used to generate the +.Nm netgroup.byuser +and +.Nm netgroup.byhosts +NIS maps. These reverse netgroup maps are used to help speed up +netgroup lookups, particularly for the +.Fn innetgr +library function. +.Pp +For example, the standard +.Nm /etc/netgroup +file may list a netgroup and a list of its members. Here, the +netgroup is considered the +.Pa key +and the member names are the +.Pa data . +By contrast, the reverse +.Nm netgroup.byusers +database lists each unique +member as the key and the netgroups to which the members belong become +the data. Seperate databases are created to hold information pertaining +to users and hosts; this allows netgroup username lookups +and netgroup hostname lookups to be performed using independent keyspaces. +.Pp +By constructing these reverse netgroup databases (and the corresponding +NIS maps) in advance, the +.Xr getnetgrent 3 +library functions are spared from having to work out the dependencies +themselves on the fly. This is important on networks with large numbers +of users and hosts, since it can take a considerable amount of time +to process very large netgroup databases. +.Pp +The +.Nm revnetgroup +command prints its results on the standard output. It is usually called +only by +.Nm /var/yp/Makefile +when rebuilding the NIS netgroup maps. +.Pp +.Sh OPTIONS +The +.Nm revnetgroup +command supports the following options: +.Bl -tag -width flag +.It Fl u +Generate netgroup.byuser output; only username information in the +original netgroup file is processed. +.It Fl h +Generate netgroup.byhost output; only hostname information in the +original netgroup file is processed. (Note at least one of the +.Fl u +or +.Fl h +flags must be specified.) +.It Op Fl f Ar netgroup_file +The +.Nm revnetgroup +command uses +.Nm /etc/netgroup +as its default input file. The +.Fl f +flag allows the user to specify an alternate input file. Specifying ``-'' +as the input file causes +.Nm revnetgroup +to read from the standard input. +.El +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /var/yp/Makefile +The Makefile that calls +.Nm yp_mkdb +and +.Nm revnetgroup +to build the NIS databases. +.It Pa /etc/netgroup +The default netgroup database file. This file is most often found +only on the NIS master server. +.El +.Sh SEE ALSO +.Xr yp 4 , +.Xr netgroup 5 , +.Xr yp_mkdb 8 , +.Xr getnetgrent 3 +.Sh AUTHOR +Bill Paul diff --git a/libexec/revnetgroup/revnetgroup.c b/libexec/revnetgroup/revnetgroup.c new file mode 100644 index 000000000000..4a3ab5aac7c5 --- /dev/null +++ b/libexec/revnetgroup/revnetgroup.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1995 + * Bill Paul . 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR CONTRIBUTORS 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. + * + * reverse netgroup map generator program + * + * Written by Bill Paul + * Center for Telecommunications Research + * Columbia University, New York City + * + * $Id$ + */ + +#include +#include +#include +#include "hash.h" + +#define LINSIZ 1024 + +/* Default location of netgroup file. */ +char *netgroup = "/etc/netgroup"; + +/* Stored hash table version of 'forward' netgroup database. */ +struct group_entry *gtable[TABLESIZE]; + +/* + * Stored hash table of 'reverse' netgroup member database + * which we will construct. + */ +struct member_entry *mtable[TABLESIZE]; + +extern void store __P(( struct group_entry ** , char *, char * )); +extern void mstore __P(( struct member_entry ** , char *, char *, char * )); +extern char *lookup __P(( struct group_entry **, char * )); + +void usage(prog) +char *prog; +{ + fprintf (stderr,"usage: %s -u|-h [-f netgroup file]\n",prog); + exit(1); +} + +extern char *optarg; + +main(argc, argv) +int argc; +char *argv[0]; +{ + FILE *fp; + char readbuf[LINSIZ]; + struct group_entry *gcur; + struct member_entry *mcur; + char *host, *user, *domain; + char ch; + char *key = NULL, *data = NULL; + int hosts, i; + + if (argc < 2) + usage(argv[0]); + + while ((ch = getopt(argc, argv, "uhf:")) != EOF) { + switch(ch) { + case 'u': + hosts = 0; + break; + case 'h': + hosts = 1; + break; + case 'f': + netgroup = optarg; + break; + default: + usage(argv[0]); + break; + } + } + + if (strcmp(netgroup, "-")) { + if ((fp = fopen(netgroup, "r")) == NULL) { + perror(netgroup); + exit(1); + } + } else { + fp = stdin; + } + + /* Stuff all the netgroup names and members into a hash table. */ + while (fgets(readbuf, LINSIZ, fp)) { + if (readbuf[0] == '#') + continue; + if ((data = (char *)(strpbrk(readbuf, " \t") + 1)) < (char *)2) + continue; + key = (char *)&readbuf; + *(data - 1) = '\0'; + store(gtable, key, data); + } + + fclose(fp); + + /* + * Find all members of each netgroup and keep track of which + * group they belong to. + */ + for (i = 0; i < TABLESIZE; i++) { + gcur = gtable[i]; + while(gcur) { + __setnetgrent(gcur->key); + while(__getnetgrent(&host, &user, &domain) != NULL) { + if (hosts ? host && strcmp(host,"-") : user && strcmp(user, "-")) + mstore(mtable, hosts ? host : user, gcur->key, domain); + } + gcur = gcur->next; + } + } + + /* Release resources used by the netgroup parser code. */ + __endnetgrent(); + + /* Spew out the results. */ + for (i = 0; i < TABLESIZE; i++) { + mcur = mtable[i]; + while(mcur) { + struct grouplist *tmp; + printf ("%s.%s\t", mcur->key, mcur->domain); + tmp = mcur->groups; + while(tmp) { + printf ("%s", tmp->groupname); + tmp = tmp->next; + if (tmp) + printf(","); + } + mcur = mcur->next; + printf ("\n"); + } + } + + /* Let the OS free all our resources. */ + exit(0); +}