Add revnetgroup from FreeBSD, written by Bill Paul <wpaul@ctr.columbia.edu>.
authormaja <maja@openbsd.org>
Tue, 15 Apr 1997 22:06:10 +0000 (22:06 +0000)
committermaja <maja@openbsd.org>
Tue, 15 Apr 1997 22:06:10 +0000 (22:06 +0000)
Hacked a bit to generate output ala Sun (handle different domains). -moj

usr.sbin/ypserv/revnetgroup/Makefile [new file with mode: 0644]
usr.sbin/ypserv/revnetgroup/hash.c [new file with mode: 0644]
usr.sbin/ypserv/revnetgroup/hash.h [new file with mode: 0644]
usr.sbin/ypserv/revnetgroup/parse_netgroup.c [new file with mode: 0644]
usr.sbin/ypserv/revnetgroup/revnetgroup.8 [new file with mode: 0644]
usr.sbin/ypserv/revnetgroup/revnetgroup.c [new file with mode: 0644]

diff --git a/usr.sbin/ypserv/revnetgroup/Makefile b/usr.sbin/ypserv/revnetgroup/Makefile
new file mode 100644 (file)
index 0000000..a96581a
--- /dev/null
@@ -0,0 +1,9 @@
+#      $OpenBSD: Makefile,v 1.1 1997/04/15 22:06:10 maja Exp $
+#      $FreeBSD: Makefile,v 1.3 1997/02/22 14:22:00 peter Exp $
+
+PROG=  revnetgroup
+SRCS=  revnetgroup.c hash.c parse_netgroup.c
+
+MAN= revnetgroup.8
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/ypserv/revnetgroup/hash.c b/usr.sbin/ypserv/revnetgroup/hash.c
new file mode 100644 (file)
index 0000000..ace2409
--- /dev/null
@@ -0,0 +1,221 @@
+/* $OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $ */
+/*
+ * Copyright (c) 1995
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  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.
+ *
+ *     $FreeBSD: hash.c,v 1.4 1997/02/22 14:22:01 peter Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "hash.h"
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $";
+#endif
+
+/*
+ * 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 hold 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 little 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 a 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,*p;
+       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) && !strcmp(cur->domain,domain)) {
+                       p = cur->groups;
+                       while(p) {
+                               if (!strcmp(p->groupname,data))
+                                       return;
+                               p = p->next;
+                       }
+                       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 = strdup(domain);
+       new->groups = tmp;
+       new->next = table[i];
+       table[i] = new;
+
+       return;
+}
diff --git a/usr.sbin/ypserv/revnetgroup/hash.h b/usr.sbin/ypserv/revnetgroup/hash.h
new file mode 100644 (file)
index 0000000..a01c28b
--- /dev/null
@@ -0,0 +1,68 @@
+/* $OpenBSD: hash.h,v 1.1 1997/04/15 22:06:12 maja Exp $ */
+/*
+ * Copyright (c) 1995
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  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.
+ *
+ *     $FreeBSD: hash.h,v 1.5 1997/02/22 14:22:02 peter Exp $
+ */
+
+/* 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 group_entry *next;
+};
+
+/* Table size (chosen arbitrarily). Not too big, not too small. */
+#define TABLESIZE 256
+#define HASH_MASK 0x000000FF
+
+#define LINSIZ 1024 * 10
+
+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 * ));
+extern void __endnetgrent __P(( void ));
+extern void __setnetgrent __P(( char * ));
+extern int __getnetgrent __P(( char **, char **, char ** ));
diff --git a/usr.sbin/ypserv/revnetgroup/parse_netgroup.c b/usr.sbin/ypserv/revnetgroup/parse_netgroup.c
new file mode 100644 (file)
index 0000000..0324515
--- /dev/null
@@ -0,0 +1,371 @@
+/* $OpenBSD: parse_netgroup.c,v 1.1 1997/04/15 22:06:13 maja Exp $ */
+/*
+ * 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.
+ *
+ *     $FreeBSD: parse_netgroup.c,v 1.5 1997/02/22 14:22:02 peter Exp $
+ */
+
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "hash.h"
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: parse_netgroup.c,v 1.1 1997/04/15 22:06:13 maja Exp $";
+#endif
+
+/*
+ * 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[];
+
+/*
+ * 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 = NULL, *olinep = NULL;
+       register int len, olen;
+       int cont;
+       struct linelist *lp;
+       char line[LINSIZ + 1];
+       char *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/usr.sbin/ypserv/revnetgroup/revnetgroup.8 b/usr.sbin/ypserv/revnetgroup/revnetgroup.8
new file mode 100644 (file)
index 0000000..aea4095
--- /dev/null
@@ -0,0 +1,138 @@
+.\"    $OpenBSD: revnetgroup.8,v 1.1 1997/04/15 22:06:14 maja Exp $
+.\" Copyright (c) 1995
+.\"    Bill Paul <wpaul@ctr.columbia.edu>.  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.
+.\"
+.\"    $FreeBSD: revnetgroup.8,v 1.4 1997/02/22 14:22:03 peter Exp $
+.\"
+.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
+YP 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
+YP 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/\<domain\>/Makefile
+when rebuilding the YP 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/\<domain\>Makefile
+The Makefile that calls
+.Nm makedbm
+and
+.Nm revnetgroup
+to build the YP databases.
+.It Pa /etc/netgroup
+The default netgroup database file. This file is most often found
+only on the YP master server.
+.El
+.Sh SEE ALSO
+.Xr getnetgrent 3 ,
+.Xr yp 8 ,
+.Xr netgroup 5 ,
+.Xr makedbm 8
+.Sh AUTHOR
+Bill Paul <wpaul@ctr.columbia.edu>
diff --git a/usr.sbin/ypserv/revnetgroup/revnetgroup.c b/usr.sbin/ypserv/revnetgroup/revnetgroup.c
new file mode 100644 (file)
index 0000000..cad2577
--- /dev/null
@@ -0,0 +1,198 @@
+/* $OpenBSD: revnetgroup.c,v 1.1 1997/04/15 22:06:15 maja Exp $ */
+/*
+ * Copyright (c) 1995
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  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 <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ *     $FreeBSD: revnetgroup.c,v 1.7 1997/03/28 15:48:15 imp Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include "hash.h"
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: revnetgroup.c,v 1.1 1997/04/15 22:06:15 maja Exp $";
+#endif
+
+/* 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];
+
+void usage(prog)
+char *prog;
+{
+       fprintf (stderr,"usage: %s -u|-h [-f netgroup file]\n",prog);
+       exit(1);
+}
+
+extern char *optarg;
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       FILE *fp;
+       char readbuf[LINSIZ];
+       struct group_entry *gcur;
+       struct member_entry *mcur;
+       char *host, *user, *domain;
+       int ch;
+       char *key = NULL, *data = NULL;
+       int hosts = -1, i;
+
+       if (argc < 2)
+               usage(argv[0]);
+
+       while ((ch = getopt(argc, argv, "uhf:")) != -1) {
+               switch(ch) {
+               case 'u':
+                       if (hosts != -1) {
+                               warnx("please use only one of -u or -h");
+                               usage(argv[0]);
+                       }
+                       hosts = 0;
+                       break;
+               case 'h':
+                       if (hosts != -1) {
+                               warnx("please use only one of -u or -h");
+                               usage(argv[0]);
+                       }
+                       hosts = 1;
+                       break;
+               case 'f':
+                       netgroup = optarg;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (hosts == -1)
+               usage(argv[0]);
+
+       if (strcmp(netgroup, "-")) {
+               if ((fp = fopen(netgroup, "r")) == NULL) {
+                       err(1,netgroup);
+               }
+       } else {
+               fp = stdin;
+       }
+
+       /* Stuff all the netgroup names and members into a hash table. */
+       while (fgets(readbuf, LINSIZ, fp)) {
+               if (readbuf[0] == '#')
+                       continue;
+               /* handle backslash line continuations */
+               while(readbuf[strlen(readbuf) - 2] == '\\') {
+                       fgets((char *)&readbuf[strlen(readbuf) - 2],
+                                       sizeof(readbuf) - strlen(readbuf), fp);
+               }
+               data = NULL;
+               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) {
+                                       if (!(host && !strcmp(host,"-"))) {
+                                               mstore(mtable,
+                                                      host ? host : "*",
+                                                      gcur->key,
+                                                      domain ? domain : "*");
+                                       }
+                               } else {
+                                       if (!(user && !strcmp(user,"-"))) {
+                                               mstore(mtable,
+                                                      user ? user : "*",
+                                                      gcur->key,
+                                                      domain ? 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);
+}