Subject: netgroup implementation
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: Christos Zoulas <christos@deshaw.com>
List: current-users
Date: 03/11/1994 14:25:58
I have just finished an implementation of SunOS style netgroups.
I have appended a shar archive of the source and a README file
describing what is done, what needs to be done and how to install
it.
Feed-bug and back reports appreciated.
Enjoy,
christos
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: README lib include netgroup_mkdb test lib/getnetgrent.c
# lib/rcmd.c include/netgroup.h netgroup_mkdb/Makefile
# netgroup_mkdb/netgroup_mkdb.8 netgroup_mkdb/netgroup_mkdb.c
# netgroup_mkdb/str.c netgroup_mkdb/str.h netgroup_mkdb/util.c
# netgroup_mkdb/util.h test/innetgr.c test/netgroup.c
# Wrapped by christos@prefect on Fri Mar 11 14:19:40 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(894 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XThis is an implementantion of SunOS style netgroups.
XNote that checking of the netgroup file is stricter than the SunOS one.
XI.e. duplicate netgroups or unreferenced names are errors.
X
XDone:
X
X - all the functions in the netgroup interface:
X
X getnetgrent()
X setnetgrent()
X endnetgrent()
X innetgr()
X
X - a netgroup_mkdb program to generate db(3) format netgroup databases
X
X - changes to rcmd.c to parse netgroups
X
X
XMissing/Unimplemented:
X
X - man pages:
X
X netgroup.5
X getnetgrent.3
X
X - src changes:
X mount, getpwent, getgrent.
X
X
XYou need to install netgroup.h in /usr/src/include and /usr/include.
XYou need to replace rcmd.c and install getnetgrent.c in /usr/src/lib/libc/net
XYou need to install the netgroup_mkdb program in /usr/src/usr.sbin
X
XAnd of course fix all the Makefiles affected.
X
XI am using this code on my machine, so if you find any bugs please let me
Xknow.
X
Xchristos
END_OF_FILE
if test 894 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test ! -d 'lib' ; then
echo shar: Creating directory \"'lib'\"
mkdir 'lib'
fi
if test ! -d 'include' ; then
echo shar: Creating directory \"'include'\"
mkdir 'include'
fi
if test ! -d 'netgroup_mkdb' ; then
echo shar: Creating directory \"'netgroup_mkdb'\"
mkdir 'netgroup_mkdb'
fi
if test ! -d 'test' ; then
echo shar: Creating directory \"'test'\"
mkdir 'test'
fi
if test -f 'lib/getnetgrent.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'lib/getnetgrent.c'\"
else
echo shar: Extracting \"'lib/getnetgrent.c'\" \(13020 characters\)
sed "s/^X//" >'lib/getnetgrent.c' <<'END_OF_FILE'
X/*
X * getnetgrent.c:
X */
X#include <stdio.h>
X#include <netgroup.h>
X#include <string.h>
X#include <fcntl.h>
X#include <err.h>
X#include <ctype.h>
X#include <stdlib.h>
X#include <db.h>
X
X#define ISSPACE(p) (isspace((unsigned char) (p)) || (p) == '\n')
X
Xstatic const char _ngoomem[] = "netgroup: %m";
Xstatic struct netgroup *_nghead, *_nglist;
Xstatic DB *_ng_db;
X
Xstruct stringlist;
X
Xstatic void downcase __P((char *));
Xstatic char *getstring __P((char **, int));
Xstatic struct netgroup *getnetgroup __P((char **));
Xstatic int lookup __P((const char *, char *, char **,
X int));
Xstatic void addgroup __P((char *, struct stringlist *,
X char *));
Xstatic int in_check __P((const char *, const char *,
X const char *, struct netgroup *));
Xstatic int in_find __P((char *, struct stringlist *,
X char *, const char *,
X const char *, const char *));
Xstatic char *in_lookup1 __P((const char *, const char *,
X const char *, int));
Xstatic int in_lookup __P((const char *, const char *,
X const char *, const char *, int));
X
X/*
X * Simple string list
X */
Xstruct stringlist {
X char **sl_str;
X size_t sl_max;
X size_t sl_cur;
X} stringlist;
X
X
X/* _ng_sl_init():
X * Initialize a string list
X */
Xstruct stringlist *
X_ng_sl_init()
X{
X struct stringlist *sl = malloc(sizeof(struct stringlist));
X sl->sl_cur = 0;
X sl->sl_max = 20;
X sl->sl_str = malloc(sl->sl_max * sizeof(char *));
X if (sl->sl_str == NULL)
X err(1, _ngoomem);
X return sl;
X}
X
X
X/* _ng_sl_add():
X * Add an item to the string list
X */
Xvoid
X_ng_sl_add(sl, name)
X struct stringlist *sl;
X char *name;
X{
X if (sl->sl_cur == sl->sl_max - 1) {
X sl->sl_max += 20;
X sl->sl_str = realloc(sl->sl_str, sl->sl_max * sizeof(char *));
X }
X sl->sl_str[sl->sl_cur++] = name;
X}
X
X
X/* _ng_sl_free():
X * Free a stringlist
X */
Xvoid
X_ng_sl_free(sl, all)
X struct stringlist *sl;
X int all;
X{
X size_t i;
X if (all)
X for (i = 0; i < sl->sl_cur; i++)
X free(sl->sl_str[i]);
X free(sl->sl_str);
X free(sl);
X}
X
X
X/* sl_find():
X * Find a name in the string list
X */
Xchar *
X_ng_sl_find(sl, name)
X struct stringlist *sl;
X char *name;
X{
X size_t i;
X for (i = 0; i < sl->sl_cur; i++)
X if (strcmp(sl->sl_str[i], name) == 0)
X return sl->sl_str[i];
X
X return NULL;
X}
X
X
X/* downcase():
X * Make a string low case
X */
Xstatic void
Xdowncase(s)
X char *s;
X{
X for (;*s; s++)
X *s = isupper((unsigned char) *s) ? tolower((unsigned char) *s) : *s;
X}
X
X
X/* getstring():
X * Get a string delimited by the character, skipping leading and
X * trailing blanks and advancing the pointer
X */
Xstatic char *
Xgetstring(pp, del)
X char **pp;
X int del;
X{
X char *sp, *ep, *dp;
X
X /* skip leading blanks */
X for (sp = *pp; *sp && ISSPACE(*sp); sp++)
X continue;
X
X /* accumulate till delimiter or space */
X for (ep = sp; *ep && *ep != del && !ISSPACE(*ep); ep++)
X continue;
X
X /* hunt for the delimiter */
X for (dp = ep; *dp && *dp != del && ISSPACE(*dp); dp++)
X continue;
X
X if (*dp != del)
X return NULL;
X
X *pp = ++dp;
X
X del = (ep - sp) + 1;
X dp = malloc(del);
X if (dp == NULL)
X err(1, _ngoomem);
X memcpy(dp, sp, del);
X dp[del-1] = '\0';
X
X return dp;
X}
X
X
X/* getnetgroup():
X * Parse a netgroup, and advance the pointer
X */
Xstatic struct netgroup *
Xgetnetgroup(pp)
X char **pp;
X{
X struct netgroup *ng = malloc(sizeof(struct netgroup));
X if (ng == NULL)
X err(1, _ngoomem);
X
X (*pp)++; /* skip '(' */
X if ((ng->ng_host = getstring(pp, ',')) == NULL)
X goto badhost;
X
X if ((ng->ng_user = getstring(pp, ',')) == NULL)
X goto baduser;
X
X if ((ng->ng_domain = getstring(pp, ')')) == NULL)
X goto baddomain;
X
X#ifdef DEBUG_NG
X (void) fprintf(stderr, "netgroup(%s,%s,%s)\n", ng->ng_host, ng->ng_user,
X ng->ng_domain);
X#endif
X downcase(ng->ng_host);
X downcase(ng->ng_user);
X downcase(ng->ng_domain);
X return ng;
X
Xbaddomain:
X free(ng->ng_user);
Xbaduser:
X free(ng->ng_host);
Xbadhost:
X free(ng);
X return NULL;
X}
X
X
X/* lookup():
X * Find the given key in the database or yp, and return its value
X * in *line; returns 1 if key was found, 0 otherwise
X */
Xstatic int
Xlookup(ypdom, name, line, bywhat)
X const char *ypdom;
X char *name;
X char **line;
X int bywhat;
X{
X#ifdef YP
X int i;
X char *map = NULL;
X#endif
X
X if (_ng_db) {
X DBT key, data;
X char *ks;
X size_t len = strlen(name) + 2;
X ks = malloc(len);
X ks[0] = bywhat;
X memcpy(&ks[1], name, len - 1);
X
X key.data = (u_char *) ks;
X key.size = len;
X
X switch ((_ng_db->get)(_ng_db, &key, &data, 0)) {
X case 0:
X free(ks);
X *line = strdup(data.data);
X if (*line == NULL)
X err(1, _ngoomem);
X return 1;
X
X case 1:
X break;
X
X case -1:
X warn("netgroup: db get");
X break;
X }
X free(ks);
X }
X
X#ifdef YP
X switch (bywhat) {
X case _NG_KEYBYNAME:
X map = "netgroup";
X break;
X
X case _NG_KEYBYUSER:
X map = "netgroup.byuser";
X break;
X
X case _NG_KEYBYHOST:
X map = "netgroup.byhost";
X break;
X
X default:
X abort();
X break;
X }
X
X
X if (ypdom && yp_match(ypdom, map, name, strlen(name), line, &i) == 0)
X return 1;
X#endif
X
X return 0;
X}
X
X
X/* _ng_parse():
X * Parse a line and return:
X * _NG_ERROR: Syntax Error
X * _NG_NONE: line was empty or a comment
X * _NG_GROUP: line had a netgroup definition, returned in ng
X * _NG_NAME: line had a netgroup name, returned in name
X *
X * Public since used by netgroup_mkdb
X */
Xint
X_ng_parse(p, name, ng)
X char **p;
X char **name;
X struct netgroup **ng;
X{
X while (**p) {
X if (**p == '#')
X /* comment */
X return _NG_NONE;
X
X while (**p && ISSPACE(**p))
X /* skipblank */
X (*p)++;
X
X if (**p == '(') {
X if ((*ng = getnetgroup(p)) == NULL) {
X warnx("netgroup: Syntax error `%s'", *p);
X return _NG_ERROR;
X }
X return _NG_GROUP;
X }
X else {
X char *np;
X for (np = *p; **p && !ISSPACE(**p); (*p)++)
X continue;
X if (np != *p) {
X int i = (*p - np) + 1;
X *name = malloc(i);
X if (*name == NULL)
X err(1, _ngoomem);
X memcpy(*name, np, i);
X downcase(*name);
X (*name)[i - 1] = '\0';
X return _NG_NAME;
X }
X }
X }
X return _NG_NONE;
X}
X
X
X/* addgroup():
X * Recursively add all the members of the netgroup to this group
X */
Xstatic void
Xaddgroup(ypdom, sl, grp)
X char *ypdom;
X struct stringlist *sl;
X char *grp;
X{
X char *line, *p;
X
X#ifdef DEBUG_NG
X (void) fprintf(stderr, "addgroup(%s)\n", grp);
X#endif
X /* check for cycles */
X if (_ng_sl_find(sl, grp) != NULL) {
X warnx("netgroup: Cycle in group `%s'", grp);
X return;
X }
X _ng_sl_add(sl, grp);
X
X /* Lookup this netgroup */
X if (!lookup(ypdom, grp, &line, _NG_KEYBYNAME))
X return;
X
X p = line;
X
X for (;;) {
X struct netgroup *ng;
X char *name;
X switch (_ng_parse(&p, &name, &ng)) {
X case _NG_NONE:
X /* Done with the line */
X free(line);
X return;
X
X case _NG_GROUP:
X /* new netgroup */
X /* add to the list */
X ng->ng_next = _nglist;
X _nglist = ng;
X break;
X
X case _NG_NAME:
X /* netgroup name */
X addgroup(ypdom, sl, name);
X break;
X
X case _NG_ERROR:
X return;
X
X default:
X abort();
X return;
X }
X }
X}
X
X
X/* in_check():
X * Compare the spec with the netgroup
X */
Xstatic int
Xin_check(host, user, domain, ng)
X const char *host;
X const char *user;
X const char *domain;
X struct netgroup *ng;
X{
X if (host != NULL && ng->ng_host[0] != '\0'
X && strcmp(ng->ng_host, host) != 0)
X return 0;
X
X if (user != NULL && ng->ng_user[0] != '\0'
X && strcmp(ng->ng_user, user) != 0)
X return 0;
X
X if (domain != NULL && ng->ng_domain[0] != '\0'
X && strcmp(ng->ng_domain, domain) != 0)
X return 0;
X
X return 1;
X}
X
X
X/* in_find():
X * Find a match for the host, user, domain spec
X */
Xstatic int
Xin_find(ypdom, sl, grp, host, user, domain)
X char *ypdom;
X struct stringlist *sl;
X char *grp;
X const char *host;
X const char *user;
X const char *domain;
X{
X char *line, *p;
X int i;
X
X#ifdef DEBUG_NG
X (void) fprintf(stderr, "in_find(%s)\n", grp);
X#endif
X /* check for cycles */
X if (_ng_sl_find(sl, grp) != NULL) {
X warnx("netgroup: Cycle in group `%s'", grp);
X return 0;
X }
X _ng_sl_add(sl, grp);
X
X /* Lookup this netgroup */
X if (!lookup(ypdom, grp, &line, _NG_KEYBYNAME))
X return 0;
X
X p = line;
X
X for (;;) {
X struct netgroup *ng;
X char *name;
X switch (_ng_parse(&p, &name, &ng)) {
X case _NG_NONE:
X /* Done with the line */
X free(line);
X return 0;
X
X case _NG_GROUP:
X /* new netgroup */
X i = in_check(host, user, domain, ng);
X free(ng->ng_host);
X free(ng->ng_user);
X free(ng->ng_domain);
X free(ng);
X if (i) {
X free(line);
X return 1;
X }
X break;
X
X case _NG_NAME:
X /* netgroup name */
X if (in_find(ypdom, sl, name, host, user, domain)) {
X free(line);
X return 1;
X }
X break;
X
X case _NG_ERROR:
X free(line);
X return 0;
X
X default:
X abort();
X return 0;
X }
X }
X}
X
X
X/* _ng_makekey():
X * Make a key from the two names given.
X * The key is of the form <name1>.<name2>
X * Names strings are replaced with * if they are empty;
X */
Xchar *
X_ng_makekey(s1, s2, len)
X const char *s1, *s2;
X size_t len;
X{
X static const char star[] = "*";
X#define STAR(s) (((s) == NULL || *(s) == '\0') ? star : s)
X char *buf = malloc(len);
X if (buf == NULL)
X err(1, _ngoomem);
X snprintf(buf, len, "%s.%s", STAR(s1), STAR(s2));
X return buf;
X}
X
X
X/* in_lookup1():
X * Fast lookup for a key in the appropriate map
X */
Xstatic char *
Xin_lookup1(ypdom, key, domain, map)
X const char *ypdom;
X const char *key;
X const char *domain;
X int map;
X{
X char *line;
X size_t len;
X char *ptr;
X int res;
X
X len = (key ? strlen(key) : 1) + (domain ? strlen(domain) : 1) + 2;
X ptr = _ng_makekey(key, domain, len);
X res = lookup(ypdom, ptr, &line, map);
X free(ptr);
X return res ? line : NULL;
X}
X
X
X/* in_lookup():
X * Fast lookup for a key in the appropriate map
X */
Xstatic int
Xin_lookup(ypdom, group, key, domain, map)
X const char *ypdom;
X const char *group;
X const char *key;
X const char *domain;
X int map;
X{
X size_t len;
X char *line, *ptr;
X /*
X * Look in group.domain group.* *.domain *.*
X */
X if ((line = in_lookup1(ypdom, key, domain, map)) == NULL)
X if ((line = in_lookup1(ypdom, NULL, domain, map)) == NULL)
X if ((line = in_lookup1(ypdom, key, NULL, map)) == NULL)
X if ((line = in_lookup1(ypdom, NULL, NULL, map)) == NULL)
X return 0;
X
X len = strlen(group);
X
X for(ptr = line; (ptr = strstr(ptr, group)) != NULL;)
X /* Make sure we did not find a substring */
X if ((ptr != line && ptr[-1] != ',') ||
X (ptr[len] != '\0' && strchr("\n\t ,", ptr[len]) == NULL))
X ptr++;
X else {
X free(line);
X return 1;
X }
X
X free(line);
X return 0;
X}
X
X
Xvoid
Xendnetgrent()
X{
X for (_nglist = _nghead; _nglist != NULL; _nglist = _nghead) {
X _nghead = _nglist->ng_next;
X free(_nglist->ng_host);
X free(_nglist->ng_user);
X free(_nglist->ng_domain);
X free(_nglist);
X }
X
X if (_ng_db) {
X (void)(_ng_db->close)(_ng_db);
X _ng_db = NULL;
X }
X}
X
X
Xvoid
Xsetnetgrent(ng)
X const char *ng;
X{
X struct stringlist *sl = _ng_sl_init();
X#ifdef YP
X char *line;
X#endif
X char *ypdom = NULL;
X
X if (_nghead != NULL)
X endnetgrent();
X
X if (_ng_db == NULL)
X _ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
X
X#ifdef YP
X /*
X * We use yp if there is a "+" in the netgroup file,
X * or if there is no netgroup file at all
X */
X if (_ng_db == NULL || lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0)
X yp_get_default_domain(&ypdom);
X else
X free(line);
X#endif
X addgroup(ypdom, sl, strdup(ng));
X _nghead = _nglist;
X _ng_sl_free(sl, 1);
X}
X
X
Xint
Xgetnetgrent(host, user, domain)
X const char **host;
X const char **user;
X const char **domain;
X{
X if (_nglist) {
X *host = _nglist->ng_host;
X *user = _nglist->ng_user;
X *domain = _nglist->ng_domain;
X _nglist = _nglist->ng_next;
X return 1;
X }
X else
X return 0;
X}
X
X
Xint
Xinnetgr(grp, host, user, domain)
X const char *grp, *host, *user, *domain;
X{
X char *ypdom = NULL;
X#ifdef YP
X char *line;
X#endif
X int found;
X
X if (_ng_db == NULL)
X _ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
X
X#ifdef YP
X /*
X * We use yp if there is a "+" in the netgroup file,
X * or if there is no netgroup file at all
X */
X if (_ng_db == NULL)
X yp_get_default_domain(&ypdom);
X else if (lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0) {
X yp_get_default_domain(&ypdom);
X free(line);
X }
X#endif
X
X /* Try the fast lookup first */
X if (domain != NULL) {
X if (host != NULL && user == NULL) {
X if (in_lookup(ypdom, grp, host, domain, _NG_KEYBYHOST))
X return 1;
X }
X else if (host == NULL && user != NULL) {
X if (in_lookup(ypdom, grp, user, domain, _NG_KEYBYUSER))
X return 1;
X }
X }
X
X {
X struct stringlist *sl = _ng_sl_init();
X /* Too bad need the slow recursive way */
X found = in_find(ypdom, sl, strdup(grp), host, user, domain);
X _ng_sl_free(sl, 1);
X }
X return found;
X}
END_OF_FILE
if test 13020 -ne `wc -c <'lib/getnetgrent.c'`; then
echo shar: \"'lib/getnetgrent.c'\" unpacked with wrong size!
fi
# end of 'lib/getnetgrent.c'
fi
if test -f 'lib/rcmd.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'lib/rcmd.c'\"
else
echo shar: Extracting \"'lib/rcmd.c'\" \(10221 characters\)
sed "s/^X//" >'lib/rcmd.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1983 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by the University of
X * California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X * may be used to endorse or promote products derived from this software
X * without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
X/*static char *sccsid = "from: @(#)rcmd.c 5.24 (Berkeley) 2/24/91";*/
Xstatic char *rcsid = "$Id: rcmd.c,v 1.1 1994/03/11 19:05:17 christos Exp $";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <sys/stat.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <netdb.h>
X#include <pwd.h>
X#include <errno.h>
X#include <stdio.h>
X#include <ctype.h>
X#include <unistd.h>
X#include <string.h>
X
Xrcmd(ahost, rport, locuser, remuser, cmd, fd2p)
X char **ahost;
X u_short rport;
X const char *locuser, *remuser, *cmd;
X int *fd2p;
X{
X int s, timo = 1, pid;
X long oldmask;
X struct sockaddr_in sin, from;
X char c;
X int lport = IPPORT_RESERVED - 1;
X struct hostent *hp;
X fd_set reads;
X
X pid = getpid();
X hp = gethostbyname(*ahost);
X if (hp == 0) {
X herror(*ahost);
X return (-1);
X }
X *ahost = hp->h_name;
X oldmask = sigblock(sigmask(SIGURG));
X for (;;) {
X s = rresvport(&lport);
X if (s < 0) {
X if (errno == EAGAIN)
X fprintf(stderr, "socket: All ports in use\n");
X else
X perror("rcmd: socket");
X sigsetmask(oldmask);
X return (-1);
X }
X fcntl(s, F_SETOWN, pid);
X bzero((char *)&sin, sizeof sin);
X sin.sin_family = hp->h_addrtype;
X bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
X sin.sin_port = rport;
X if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
X break;
X (void) close(s);
X if (errno == EADDRINUSE) {
X lport--;
X continue;
X }
X if (errno == ECONNREFUSED && timo <= 16) {
X sleep(timo);
X timo *= 2;
X continue;
X }
X if (hp->h_addr_list[1] != NULL) {
X int oerrno = errno;
X
X fprintf(stderr,
X "connect to address %s: ", inet_ntoa(sin.sin_addr));
X errno = oerrno;
X perror(0);
X hp->h_addr_list++;
X bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
X hp->h_length);
X fprintf(stderr, "Trying %s...\n",
X inet_ntoa(sin.sin_addr));
X continue;
X }
X perror(hp->h_name);
X sigsetmask(oldmask);
X return (-1);
X }
X lport--;
X if (fd2p == 0) {
X write(s, "", 1);
X lport = 0;
X } else {
X char num[8];
X int s2 = rresvport(&lport), s3;
X int len = sizeof (from);
X
X if (s2 < 0)
X goto bad;
X listen(s2, 1);
X (void) sprintf(num, "%d", lport);
X if (write(s, num, strlen(num)+1) != strlen(num)+1) {
X perror("write: setting up stderr");
X (void) close(s2);
X goto bad;
X }
X FD_ZERO(&reads);
X FD_SET(s, &reads);
X FD_SET(s2, &reads);
X errno = 0;
X if (select(32, &reads, 0, 0, 0) < 1 ||
X !FD_ISSET(s2, &reads)) {
X if (errno != 0)
X perror("select: setting up stderr");
X else
X fprintf(stderr,
X "select: protocol failure in circuit setup.\n");
X (void) close(s2);
X goto bad;
X }
X s3 = accept(s2, (struct sockaddr *)&from, &len);
X (void) close(s2);
X if (s3 < 0) {
X perror("accept");
X lport = 0;
X goto bad;
X }
X *fd2p = s3;
X from.sin_port = ntohs((u_short)from.sin_port);
X if (from.sin_family != AF_INET ||
X from.sin_port >= IPPORT_RESERVED ||
X from.sin_port < IPPORT_RESERVED / 2) {
X fprintf(stderr,
X "socket: protocol failure in circuit setup.\n");
X goto bad2;
X }
X }
X (void) write(s, locuser, strlen(locuser)+1);
X (void) write(s, remuser, strlen(remuser)+1);
X (void) write(s, cmd, strlen(cmd)+1);
X if (read(s, &c, 1) != 1) {
X perror(*ahost);
X goto bad2;
X }
X if (c != 0) {
X while (read(s, &c, 1) == 1) {
X (void) write(2, &c, 1);
X if (c == '\n')
X break;
X }
X goto bad2;
X }
X sigsetmask(oldmask);
X return (s);
Xbad2:
X if (lport)
X (void) close(*fd2p);
Xbad:
X (void) close(s);
X sigsetmask(oldmask);
X return (-1);
X}
X
Xrresvport(alport)
X int *alport;
X{
X struct sockaddr_in sin;
X int s;
X
X sin.sin_family = AF_INET;
X sin.sin_addr.s_addr = INADDR_ANY;
X s = socket(AF_INET, SOCK_STREAM, 0);
X if (s < 0)
X return (-1);
X for (;;) {
X sin.sin_port = htons((u_short)*alport);
X if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
X return (s);
X if (errno != EADDRINUSE) {
X (void) close(s);
X return (-1);
X }
X (*alport)--;
X if (*alport == IPPORT_RESERVED/2) {
X (void) close(s);
X errno = EAGAIN; /* close */
X return (-1);
X }
X }
X}
X
Xint _check_rhosts_file = 1;
X
Xruserok(rhost, superuser, ruser, luser)
X const char *rhost, *ruser, *luser;
X int superuser;
X{
X FILE *hostf;
X char fhost[MAXHOSTNAMELEN];
X int first = 1;
X register char *sp, *p;
X int baselen = -1;
X char domain[MAXHOSTNAMELEN];
X
X#ifdef YP
X getdomainname(domain, sizeof(domain));
X#endif
X
X sp = (char *)rhost;
X p = fhost;
X while (*sp) {
X if (*sp == '.') {
X if (baselen == -1)
X baselen = sp - rhost;
X *p++ = *sp++;
X } else {
X *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
X }
X }
X *p = '\0';
X hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r");
Xagain:
X if (hostf) {
X if (!_validuser(hostf, fhost, luser, ruser, baselen, domain)) {
X (void) fclose(hostf);
X return(0);
X }
X (void) fclose(hostf);
X }
X if (first == 1 && (_check_rhosts_file || superuser)) {
X struct stat sbuf;
X struct passwd *pwd;
X char pbuf[MAXPATHLEN];
X
X first = 0;
X if ((pwd = getpwnam(luser)) == NULL)
X return(-1);
X (void)strcpy(pbuf, pwd->pw_dir);
X (void)strcat(pbuf, "/.rhosts");
X if ((hostf = fopen(pbuf, "r")) == NULL)
X return(-1);
X /*
X * if owned by someone other than user or root or if
X * writeable by anyone but the owner, quit
X */
X if (fstat(fileno(hostf), &sbuf) ||
X sbuf.st_uid && sbuf.st_uid != pwd->pw_uid ||
X sbuf.st_mode&022) {
X fclose(hostf);
X return(-1);
X }
X goto again;
X }
X return (-1);
X}
X
X/* don't make static, used by lpd(8) */
X_validuser(hostf, rhost, luser, ruser, baselen, domain)
X char *rhost, *luser, *ruser;
X FILE *hostf;
X int baselen;
X char *domain;
X{
X register char *p;
X char *auser, ahost[MAXHOSTNAMELEN];
X static int _checkhost();
X int hostok, userok; /* -1 = deny, 0 = no match, 1 = accept */
X
X while (fgets(ahost, sizeof (ahost), hostf)) {
X p = ahost;
X while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
X *p = isupper(*p) ? tolower(*p) : *p;
X p++;
X }
X if (*p == ' ' || *p == '\t') {
X *p++ = '\0';
X while (*p == ' ' || *p == '\t')
X p++;
X auser = p;
X while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
X p++;
X } else
X auser = p;
X *p = '\0';
X auser = *auser ? auser : luser;
X#ifdef YP
X if (ahost[0] == '+')
X switch (ahost[1]) {
X case '\0':
X hostok = 1;
X break;
X
X case '@':
X hostok = innetgr(&ahost[2], rhost, NULL, domain);
X break;
X
X default:
X hostok = _checkhost(rhost, &ahost[1], baselen);
X break;
X }
X else if (ahost[0] == '-')
X switch (ahost[1]) {
X case '\0':
X hostok = -1;
X break;
X
X case '@':
X hostok = -innetgr(rhost, &ahost[2], NULL, baselen);
X break;
X
X default:
X hostok = -_checkhost(rhost, &ahost[1], baselen);
X break;
X }
X else
X#endif
X hostok = _checkhost(rhost, ahost, baselen);
X
X#ifdef YP
X if (auser[0] == '+')
X switch (auser[1]) {
X case '\0':
X userok = 1;
X break;
X
X case '@':
X userok = innetgr(ruser, NULL, &auser[2], 0);
X break;
X
X default:
X userok = strcmp(ruser, &auser[1]) == 0;
X break;
X }
X else if (auser[0] == '-')
X switch (auser[1]) {
X case '\0':
X userok = -1;
X break;
X
X case '@':
X userok = -innetgr(ruser, NULL, &auser[2], 0);
X break;
X
X default:
X userok = -(strcmp(ruser, &auser[1]) == 0);
X break;
X }
X else
X#endif
X userok = strcmp(ruser, auser) == 0;
X
X /* Check if one component did not match */
X if (hostok == 0 || userok == 0)
X continue;
X
X /* Check if we got a forbidden pair */
X if (userok == -1 || hostok == -1)
X return -1;
X
X /* Check if we got a valid pair */
X if (hostok == 1 && userok == 1)
X return 0;
X }
X return (-1);
X}
X
Xstatic int
X_checkhost(rhost, lhost, len)
X char *rhost, *lhost;
X int len;
X{
X static char ldomain[MAXHOSTNAMELEN + 1];
X static char *domainp = NULL;
X static int nodomain = 0;
X register char *cp;
X
X if (len == -1)
X return(!strcmp(rhost, lhost));
X if (strncmp(rhost, lhost, len))
X return(0);
X if (!strcmp(rhost, lhost))
X return(1);
X if (*(lhost + len) != '\0')
X return(0);
X if (nodomain)
X return(0);
X if (!domainp) {
X if (gethostname(ldomain, sizeof(ldomain)) == -1) {
X nodomain = 1;
X return(0);
X }
X ldomain[MAXHOSTNAMELEN] = NULL;
X if ((domainp = index(ldomain, '.')) == (char *)NULL) {
X nodomain = 1;
X return(0);
X }
X for (cp = ++domainp; *cp; ++cp)
X if (isupper(*cp))
X *cp = tolower(*cp);
X }
X return(!strcmp(domainp, rhost + len +1));
X}
END_OF_FILE
if test 10221 -ne `wc -c <'lib/rcmd.c'`; then
echo shar: \"'lib/rcmd.c'\" unpacked with wrong size!
fi
# end of 'lib/rcmd.c'
fi
if test -f 'include/netgroup.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'include/netgroup.h'\"
else
echo shar: Extracting \"'include/netgroup.h'\" \(939 characters\)
sed "s/^X//" >'include/netgroup.h' <<'END_OF_FILE'
X#ifndef _NETGROUP_H_
X#define _NETGROUP_H_
X
X#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
X
X#define _PATH_NETGROUP "/etc/netgroup"
X
X#define _PATH_NETGROUP_DB "/etc/netgroup.db"
X
X#define _PATH_NETGROUP_MKDB "/usr/sbin/netgroup_mkdb"
X
X#define _NG_KEYBYNAME '1' /* stored by name */
X#define _NG_KEYBYUSER '2' /* stored by user */
X#define _NG_KEYBYHOST '3' /* stored by host */
X
X#define _NG_ERROR -1
X#define _NG_NONE 0
X#define _NG_NAME 1
X#define _NG_GROUP 2
X
Xstruct netgroup {
X char *ng_host; /* host name */
X char *ng_user; /* user name */
X char *ng_domain; /* domain name */
X struct netgroup *ng_next; /* thread */
X};
X
X#include <sys/cdefs.h>
X
X__BEGIN_DECLS
Xvoid setnetgrent __P((const char *));
Xint getnetgrent __P((const char **, const char **, const char **));
Xvoid endnetgrent __P((void));
Xint innetgr __P((const char *, const char *, const char *,
X const char *));
X__END_DECLS
X#endif
X
X#endif /* !_NETGROUP_H_ */
END_OF_FILE
if test 939 -ne `wc -c <'include/netgroup.h'`; then
echo shar: \"'include/netgroup.h'\" unpacked with wrong size!
fi
# end of 'include/netgroup.h'
fi
if test -f 'netgroup_mkdb/Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/Makefile'\"
else
echo shar: Extracting \"'netgroup_mkdb/Makefile'\" \(203 characters\)
sed "s/^X//" >'netgroup_mkdb/Makefile' <<'END_OF_FILE'
X# from: @(#)Makefile 5.1 (Berkeley) 3/8/91
X# $Id: Makefile,v 1.1 1994/03/11 19:06:13 christos Exp $
X
XPROG= netgroup_mkdb
XSRCS= netgroup_mkdb.c util.c str.c
XMAN8= netgroup_mkdb.0
X
X.include <bsd.prog.mk>
X
END_OF_FILE
if test 203 -ne `wc -c <'netgroup_mkdb/Makefile'`; then
echo shar: \"'netgroup_mkdb/Makefile'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/Makefile'
fi
if test -f 'netgroup_mkdb/netgroup_mkdb.8' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/netgroup_mkdb.8'\"
else
echo shar: Extracting \"'netgroup_mkdb/netgroup_mkdb.8'\" \(869 characters\)
sed "s/^X//" >'netgroup_mkdb/netgroup_mkdb.8' <<'END_OF_FILE'
X.Dd February 3, 1994
X.Dt NETGROUP_MKDB 8
X.Os
X.Sh NAME
X.Nm netgroup_mkdb
X.Nd generate the netgroup databases
X.Sh SYNOPSIS
X.Nm netgroup_mkdb
X.Op Fl o Ar database
X.Ar file
X.Sh DESCRIPTION
X.Nm Netgroup_mkdb
Xcreates
X.Xr db 3
Xstyle databases for the specified file.
XThese databases are then installed into
X.Pa /etc/netgroup.db.
XThe file must be in the correct format (see
X.Xr netgroup 5 ).
X.Pp
XThe options are as follows:
X.Bl -tag -width indent
X.It Fl o Ar database
XPut the output database in the named file.
X.El
X.Pp
XThe databases are used by the C library netgroup routines (see
X.Xr getnetgrent 3 ).
X.Pp
X.Nm Netgroup_mkdb
Xexits zero on success, non-zero on failure.
X.Sh FILES
X.Bl -tag -width 24n -compact
X.It Pa /etc/netgroup.db
XThe current netgroup database
X.It Pa /etc/netgroup
XThe current netgroup file
X.El
X.Sh SEE ALSO
X.Xr db 3 ,
X.Xr getnetgrent 3 ,
X.Xr netgroup 5
END_OF_FILE
if test 869 -ne `wc -c <'netgroup_mkdb/netgroup_mkdb.8'`; then
echo shar: \"'netgroup_mkdb/netgroup_mkdb.8'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/netgroup_mkdb.8'
fi
if test -f 'netgroup_mkdb/netgroup_mkdb.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/netgroup_mkdb.c'\"
else
echo shar: Extracting \"'netgroup_mkdb/netgroup_mkdb.c'\" \(11609 characters\)
sed "s/^X//" >'netgroup_mkdb/netgroup_mkdb.c' <<'END_OF_FILE'
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdlib.h>
X#include <stddef.h>
X#include <unistd.h>
X#include <fcntl.h>
X#include <db.h>
X#include <err.h>
X#include <errno.h>
X#include <stdio.h>
X#include <string.h>
X#include <netgroup.h>
X#include <assert.h>
X
X#include "str.h"
X#include "util.h"
X
X#define NEW(a) (a *) emalloc(sizeof(a))
X
Xstruct nentry {
X int n_type;
X size_t n_size; /* Buffer size required for printing */
X union {
X char *_name;
X struct netgroup *_group;
X } n;
X#define n_name n._name
X#define n_group n._group
X struct nentry *n_next;
X};
X
X
Xstruct stringlist;
Xextern struct stringlist *_ng_sl_init __P((void));
Xextern void _ng_sl_add __P((struct stringlist *, char *));
Xextern void _ng_sl_free __P((struct stringlist *, int));
Xextern char *_ng_sl_find __P((struct stringlist *, char *));
X
Xextern char *_ng_makekey __P((const char *, const char *, size_t));
Xextern int _ng_parse __P((char **, char **, struct netgroup **));
X
Xstatic DB *ng_insert __P((DB *, const char *));
Xstatic void ng_reventry __P((DB *, DB *, struct nentry *, char *,
X size_t, struct stringlist *));
X
Xstatic void ng_print __P((struct nentry *, struct string *));
Xstatic void ng_rprint __P((DB *, struct string *));
Xstatic DB *ng_reverse __P((DB *, size_t));
Xstatic DB *ng_load __P((const char *));
Xstatic void ng_write __P((DB *, DB *, int));
Xstatic void ng_rwrite __P((DB *, DB *, int));
Xstatic void usage __P((void));
X
X#ifdef DEBUG_NG
Xstatic void ng_dump __P((DB *));
Xstatic void ng_rdump __P((DB *));
X#endif /* DEBUG_NG */
X
Xstatic char *dbname = _PATH_NETGROUP_DB;
X
Xint
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X DB *db, *ndb, *hdb, *udb;
X int ch;
X
X while ((ch = getopt(argc, argv, "o:")) != EOF)
X switch(ch) {
X case 'o':
X dbname = optarg;
X break;
X
X case '?':
X default:
X usage();
X }
X
X argc -= optind;
X argv += optind;
X
X if (argc != 1)
X usage();
X
X /* Read and parse the netgroup file */
X ndb = ng_load(*argv);
X#ifdef DEBUG_NG
X (void) fprintf(stderr, "#### Database\n");
X ng_dump(ndb);
X#endif
X
X /* Reverse the database by host */
X hdb = ng_reverse(ndb, offsetof(struct netgroup, ng_host));
X#ifdef DEBUG_NG
X (void) fprintf(stderr, "#### Reverse by host\n");
X ng_rdump(hdb);
X#endif
X
X /* Reverse the database by user */
X udb = ng_reverse(ndb, offsetof(struct netgroup, ng_user));
X#ifdef DEBUG_NG
X (void) fprintf(stderr, "#### Reverse by user\n");
X ng_rdump(udb);
X#endif
X
X db = dbopen(dbname, O_RDWR|O_CREAT|O_EXCL,
X (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH), DB_HASH, NULL);
X if (!db)
X err(1, dbname);
X
X ng_write(db, ndb, _NG_KEYBYNAME);
X ng_rwrite(db, udb, _NG_KEYBYUSER);
X ng_rwrite(db, hdb, _NG_KEYBYHOST);
X (db->close)(db);
X return 0;
X}
X
X
X/* ng_load():
X * Load the netgroup database from a file
X */
Xstatic DB *
Xng_load(fname)
X const char *fname;
X{
X FILE *fp;
X DB *db;
X char *buf;
X size_t size;
X
X /* Open the netgroup file */
X if ((fp = fopen(fname, "r")) == NULL)
X err(1, fname);
X
X db = dbopen(NULL, O_RDWR|O_CREAT|O_EXCL, 0, DB_HASH, NULL);
X
X if (db == NULL)
X err(1, "dbopen");
X
X while ((buf = getline(fp, &size)) != NULL) {
X struct nentry *tail = NULL, *head = NULL;
X char *p = buf;
X
X while (p != NULL) {
X char *name;
X struct netgroup *ng;
X
X switch (_ng_parse(&p, &name, &ng)) {
X case _NG_NONE:
X /* done with this one */
X p = NULL;
X free(buf);
X if (head != NULL) {
X DBT data, key;
X key.data = (u_char *) head->n_name;
X key.size = strlen(head->n_name) + 1;
X data.data = (u_char *) &head;
X data.size = sizeof(&head);
X switch ((db->put)(db, &key, &data, R_NOOVERWRITE)) {
X case 0:
X break;
X
X case 1:
X warnx("Duplicate entry netgroup `%s'\n",
X head->n_name);
X break;
X
X case -1:
X err(1, "put");
X break;
X
X default:
X abort();
X break;
X }
X }
X break;
X
X case _NG_NAME:
X {
X struct nentry* e = NEW(struct nentry);
X e->n_type = _NG_NAME;
X e->n_name = name;
X e->n_next = NULL;
X e->n_size = size;
X if (tail == NULL) {
X head = tail = e;
X }
X else {
X tail->n_next = e;
X tail = e;
X }
X }
X break;
X
X case _NG_GROUP:
X if (tail == NULL)
X errx(1, "no netgroup key");
X else {
X struct nentry* e = NEW(struct nentry);
X
X e->n_type = _NG_GROUP;
X e->n_group = ng;
X e->n_next = NULL;
X e->n_size = size;
X tail->n_next = e;
X tail = e;
X }
X break;
X
X default:
X abort();
X break;
X }
X }
X }
X (void) fclose(fp);
X return db;
X}
X
X
X/* ng_insert():
X * Insert named key into the database,
X * and return its associated string database
X */
Xstatic DB *
Xng_insert(db, name)
X DB *db;
X const char *name;
X{
X DB *xdb = NULL;
X DBT key, data;
X
X key.data = (u_char *) name;
X key.size = strlen(name) + 1;
X
X switch ((db->get)(db, &key, &data, 0)) {
X case 0:
X xdb = *((DB **) data.data);
X break;
X
X case 1:
X xdb = dbopen(NULL, O_RDWR|O_CREAT|O_EXCL, 0, DB_HASH, NULL);
X if (xdb == NULL)
X err(1, "dbopen");
X
X data.data = (u_char *) &xdb;
X data.size = sizeof(&xdb);
X switch ((db->put)(db, &key, &data, R_NOOVERWRITE)) {
X case 0:
X break;
X
X case -1:
X err(1, "db put `%s'", name);
X break;
X
X case 1:
X default:
X abort();
X }
X break;
X
X case -1:
X err(1, "db get `%s'", name);
X break;
X
X default:
X abort();
X break;
X }
X
X return xdb;
X}
X
X
X/* ng_reventry():
X * Recursively add all the netgroups to the group entry.
X */
Xstatic void
Xng_reventry(db, udb, fe, name, s, ss)
X DB *db, *udb;
X struct nentry *fe;
X char *name;
X size_t s;
X struct stringlist *ss;
X{
X DBT key, data;
X struct nentry *e;
X
X if (_ng_sl_find(ss, name) != NULL) {
X warnx("Cycle in netgroup `%s'", name);
X return;
X }
X _ng_sl_add(ss, name);
X
X for (e = fe->n_next; e != NULL; e = e->n_next) {
X switch (e->n_type) {
X case _NG_GROUP:
X {
X struct netgroup *ng = e->n_group;
X char *p = _ng_makekey(*((char **) (((char *) ng) + s)),
X ng->ng_domain, e->n_size);
X DB *xdb = ng_insert(udb, p);
X key.data = (u_char *) name;
X key.size = strlen(name) + 1;
X data.data = NULL;
X data.size = 0;
X switch ((xdb->put)(xdb, &key, &data, R_NOOVERWRITE)) {
X case 0:
X case 1:
X break;
X
X case -1:
X err(1, "db put `%s'", name);
X return;
X
X default:
X abort();
X break;
X }
X free(p);
X }
X break;
X
X case _NG_NAME:
X key.data = (u_char *) e->n_name;
X key.size = strlen(e->n_name) + 1;
X switch ((db->get)(db, &key, &data, 0)) {
X case 0:
X fe = *((struct nentry **) data.data);
X ng_reventry(db, udb, fe, name, s, ss);
X break;
X
X case 1:
X break;
X
X case -1:
X err(1, "db get `%s'", e->n_name);
X return;
X
X default:
X abort();
X return;
X }
X break;
X
X default:
X abort();
X break;
X }
X }
X}
X
X
X/* ng_reverse():
X * Reverse the database
X */
Xstatic DB *
Xng_reverse(db, s)
X DB *db;
X size_t s;
X{
X int pos;
X struct stringlist *sl;
X DBT key, data;
X DB *udb = dbopen(NULL, O_RDWR|O_CREAT|O_EXCL, 0, DB_HASH, NULL);
X
X if (udb == NULL)
X err(1, "dbopen");
X
X for (pos = R_FIRST;; pos = R_NEXT)
X switch ((db->seq)(db, &key, &data, pos)) {
X case 0:
X sl = _ng_sl_init();
X ng_reventry(db, udb, *((struct nentry **) data.data),
X (char *) key.data, s, sl);
X _ng_sl_free(sl, 0);
X break;
X
X case 1:
X return udb;
X
X case -1:
X err(1, "seq");
X return udb;
X }
X
X return udb;
X}
X
X
X/* ng_print():
X * Pretty print a netgroup entry
X */
Xstatic void
Xng_print(e, str)
X struct nentry *e;
X struct string *str;
X{
X char *ptr = emalloc(e->n_size);
X
X for (e = e->n_next; e != NULL; e = e->n_next) {
X switch (e->n_type) {
X case _NG_NAME:
X (void) snprintf(ptr, e->n_size, "%s", e->n_name);
X break;
X
X case _NG_GROUP:
X (void) snprintf(ptr, e->n_size, "(%s,%s,%s)", e->n_group->ng_host,
X e->n_group->ng_user, e->n_group->ng_domain);
X break;
X
X default:
X errx(1, "Internal error: Bad netgroup type\n");
X break;
X }
X str_append(str, ptr, ' ');
X }
X free(ptr);
X return;
X}
X
X
X/* ng_rprint():
X * Pretty print all reverse netgroup mappings in the given entry
X */
Xstatic void
Xng_rprint(db, str)
X DB *db;
X struct string *str;
X{
X int pos;
X DBT key, data;
X
X for (pos = R_FIRST;; pos = R_NEXT)
X switch ((db->seq)(db, &key, &data, pos)) {
X case 0:
X str_append(str, (char *) key.data, ',');
X break;
X
X case 1:
X return;
X
X default:
X err(1, "seq");
X break;
X }
X
X return;
X}
X
X
X#ifdef DEBUG_NG
X/* ng_dump():
X * Pretty print all netgroups in the given database
X */
Xstatic void
Xng_dump(db)
X DB *db;
X{
X int pos;
X DBT key, data;
X
X for (pos = R_FIRST;; pos = R_NEXT)
X switch ((db->seq)(db, &key, &data, pos)) {
X case 0:
X {
X struct nentry *e = *((struct nentry **) data.data);
X struct string buf;
X str_init(&buf);
X assert(e->n_type == _NG_NAME);
X
X ng_print(e, &buf);
X (void) fprintf(stderr, "%s\t%s\n", e->n_name,
X buf.s_str ? buf.s_str : "");
X str_free(&buf);
X }
X break;
X
X case 1:
X return;
X
X default:
X err(1, "seq");
X return;
X }
X}
X
X
X/* ng_rdump():
X * Pretty print all reverse mappings in the given database
X */
Xstatic void
Xng_rdump(db)
X DB *db;
X{
X int pos;
X DBT key, data;
X
X for (pos = R_FIRST;; pos = R_NEXT)
X switch ((db->seq)(db, &key, &data, pos)) {
X case 0:
X {
X DB *xdb = *((DB **) data.data);
X struct string buf;
X str_init(&buf);
X ng_rprint(xdb, &buf);
X (void) fprintf(stderr, "%s\t%s\n", (char *) key.data,
X buf.s_str ? buf.s_str : "");
X str_free(&buf);
X }
X break;
X
X case 1:
X return;
X
X default:
X err(1, "seq");
X return;
X }
X}
X#endif /* DEBUG_NG */
X
X
X/* ng_write():
X * Dump the database into a file.
X */
Xstatic void
Xng_write(odb, idb, k)
X DB *odb, *idb;
X int k;
X{
X int pos;
X DBT key, data;
X
X for (pos = R_FIRST;; pos = R_NEXT)
X switch ((idb->seq)(idb, &key, &data, pos)) {
X case 0:
X {
X struct nentry *e = *((struct nentry **) data.data);
X struct string skey, sdata;
X str_init(&skey);
X str_init(&sdata);
X assert(e->n_type == _NG_NAME);
X
X str_prepend(&skey, e->n_name, k);
X ng_print(e, &sdata);
X key.data = (u_char *) skey.s_str;
X key.size = skey.s_len + 1;
X data.data = (u_char *) sdata.s_str;
X data.size = sdata.s_len + 1;
X
X switch ((odb->put)(odb, &key, &data, R_NOOVERWRITE)) {
X case 0:
X break;
X
X case -1:
X err(1, "put");
X break;
X
X case 1:
X default:
X abort();
X break;
X }
X
X str_free(&skey);
X str_free(&sdata);
X }
X break;
X
X case 1:
X return;
X
X default:
X err(1, "seq");
X return;
X }
X}
X
X
X/* ng_rwrite():
X * Write the database
X */
Xstatic void
Xng_rwrite(odb, idb, k)
X DB *odb;
X DB *idb;
X int k;
X{
X int pos;
X DBT key, data;
X
X for (pos = R_FIRST;; pos = R_NEXT)
X switch ((idb->seq)(idb, &key, &data, pos)) {
X case 0:
X {
X DB *xdb = *((DB **) data.data);
X struct string skey, sdata;
X str_init(&skey);
X str_init(&sdata);
X
X str_prepend(&skey, (char *) key.data, k);
X ng_rprint(xdb, &sdata);
X key.data = (u_char *) skey.s_str;
X key.size = skey.s_len + 1;
X data.data = (u_char *) sdata.s_str;
X data.size = sdata.s_len + 1;
X
X switch ((odb->put)(odb, &key, &data, R_NOOVERWRITE)) {
X case 0:
X break;
X
X case -1:
X err(1, "put");
X break;
X
X case 1:
X default:
X abort();
X break;
X }
X
X str_free(&skey);
X str_free(&sdata);
X }
X break;
X
X case 1:
X return;
X
X default:
X err(1, "seq");
X return;
X }
X}
X
X
X/* usage():
X * Print usage message and exit
X */
Xstatic void
Xusage()
X{
X extern const char *__progname;
X fprintf(stderr, "usage: %s [-o db] file\n", __progname);
X exit(1);
X}
END_OF_FILE
if test 11609 -ne `wc -c <'netgroup_mkdb/netgroup_mkdb.c'`; then
echo shar: \"'netgroup_mkdb/netgroup_mkdb.c'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/netgroup_mkdb.c'
fi
if test -f 'netgroup_mkdb/str.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/str.c'\"
else
echo shar: Extracting \"'netgroup_mkdb/str.c'\" \(1295 characters\)
sed "s/^X//" >'netgroup_mkdb/str.c' <<'END_OF_FILE'
X/*
X * Counted strings
X */
X#include <stdlib.h>
X
X#include "util.h"
X#include "str.h"
X
X/* str_init():
X * Initialize string
X */
Xvoid
Xstr_init(s)
X struct string *s;
X{
X s->s_str = NULL;
X s->s_len = 0;
X}
X
X
X/* str_append():
X * Append string allocating buffer as necessary
X */
Xvoid
Xstr_append(buf, str, del)
X struct string *buf;
X const char *str;
X int del;
X{
X size_t len = strlen(str) + 1;
X if (buf->s_str == NULL)
X buf->s_str = emalloc(len);
X else {
X buf->s_str = erealloc(buf->s_str, buf->s_len + len + 1);
X if (del)
X buf->s_str[buf->s_len++] = del;
X }
X memcpy(&buf->s_str[buf->s_len], str, len);
X buf->s_len += len - 1;
X}
X
X/* str_prepend():
X * Prepend string allocating buffer as necessary
X */
Xvoid
Xstr_prepend(buf, str, del)
X struct string *buf;
X const char *str;
X int del;
X{
X size_t len = strlen(str) + 1;
X char *ptr, *sptr;
X
X sptr = ptr = emalloc(buf->s_len + len + 1);
X if (del)
X *ptr++ = del;
X memcpy(ptr, str, len);
X if (buf->s_str) {
X memcpy(&ptr[len - 1], buf->s_str, buf->s_len);
X free(buf->s_str);
X }
X buf->s_str = sptr;
X buf->s_len += len - 1;
X if (del)
X buf->s_len++;
X
X}
X
X/* str_free():
X * Free a string
X */
Xvoid
Xstr_free(s)
X struct string *s;
X{
X free(s->s_str);
X s->s_str = NULL;
X s->s_len = 0;
X}
END_OF_FILE
if test 1295 -ne `wc -c <'netgroup_mkdb/str.c'`; then
echo shar: \"'netgroup_mkdb/str.c'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/str.c'
fi
if test -f 'netgroup_mkdb/str.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/str.h'\"
else
echo shar: Extracting \"'netgroup_mkdb/str.h'\" \(350 characters\)
sed "s/^X//" >'netgroup_mkdb/str.h' <<'END_OF_FILE'
X/* Counted strings */
X
X#include <sys/types.h>
X#include <sys/cdefs.h>
X
Xstruct string {
X char *s_str;
X size_t s_len;
X};
X
X__BEGIN_DECLS
Xvoid str_init __P((struct string *));
Xvoid str_append __P((struct string *, const char *, int));
Xvoid str_prepend __P((struct string *, const char *, int));
Xvoid str_free __P((struct string *));
X__END_DECLS
END_OF_FILE
if test 350 -ne `wc -c <'netgroup_mkdb/str.h'`; then
echo shar: \"'netgroup_mkdb/str.h'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/str.h'
fi
if test -f 'netgroup_mkdb/util.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/util.c'\"
else
echo shar: Extracting \"'netgroup_mkdb/util.c'\" \(1049 characters\)
sed "s/^X//" >'netgroup_mkdb/util.c' <<'END_OF_FILE'
X#include <err.h>
X#include <stdlib.h>
X
X#include "util.h"
X
X/* emalloc():
X * Error checked malloc
X */
Xvoid *
Xemalloc(s)
X size_t s;
X{
X void *ptr = malloc(s);
X if (ptr == NULL)
X /* Crappy gcc warning! */
X err(1, "%s", "");
X return ptr;
X}
X
X
X/* erealloc():
X * Error checked realloc
X */
Xvoid *
Xerealloc(p, s)
X void *p;
X size_t s;
X{
X void *ptr = realloc(p, s);
X if (ptr == NULL)
X /* Crappy gcc warning! */
X err(1, "%s", "");
X return ptr;
X}
X
X
X/* getline():
X * Read a line from a file parsing continuations ending in \
X * and eliminating trailing newlines.
X */
Xchar *
Xgetline(fp, size)
X FILE *fp;
X size_t *size;
X{
X size_t s, len = 0;
X char *buf = NULL;
X char *ptr;
X int cnt = 1;
X
X while (cnt) {
X if ((ptr = fgetln(fp, &s)) == NULL) {
X *size = len;
X return buf;
X }
X ptr[--s] = '\0'; /* Nuke newline */
X if ((cnt = (ptr[s - 1] == '\\')) != 0) /* check for \\ */
X ptr[s--] = '\0';
X
X buf = erealloc(buf, len + s + 1);
X memcpy(buf + len, ptr, s + 1);
X len += s;
X }
X *size = len;
X return buf;
X}
END_OF_FILE
if test 1049 -ne `wc -c <'netgroup_mkdb/util.c'`; then
echo shar: \"'netgroup_mkdb/util.c'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/util.c'
fi
if test -f 'netgroup_mkdb/util.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'netgroup_mkdb/util.h'\"
else
echo shar: Extracting \"'netgroup_mkdb/util.h'\" \(199 characters\)
sed "s/^X//" >'netgroup_mkdb/util.h' <<'END_OF_FILE'
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/cdefs.h>
X
X__BEGIN_DECLS
Xvoid *emalloc __P((size_t));
Xvoid *erealloc __P((void *, size_t));
Xchar *getline __P((FILE *, size_t *));
X__END_DECLS
X
END_OF_FILE
if test 199 -ne `wc -c <'netgroup_mkdb/util.h'`; then
echo shar: \"'netgroup_mkdb/util.h'\" unpacked with wrong size!
fi
# end of 'netgroup_mkdb/util.h'
fi
if test -f 'test/innetgr.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test/innetgr.c'\"
else
echo shar: Extracting \"'test/innetgr.c'\" \(801 characters\)
sed "s/^X//" >'test/innetgr.c' <<'END_OF_FILE'
X/*
X * innetgr - Print if a user domain host is in group group
X * Options:
X * -u - user name
X * -d - domain name
X * -h - hostname
X */
X#include <stdio.h>
X#include <stdlib.h>
X
Xmain(argc, argv)
X char **argv;
X{
X char *p[3], *index();
X int i = 0, c;
X char *user = NULL;
X char *host = NULL;
X char *domain = NULL;
X
X while ((c = getopt(argc, argv, "h:u:d:")) != EOF)
X switch (c) {
X case 'u':
X user = optarg;
X break;
X case 'h':
X host = optarg;
X break;
X case 'd':
X domain = optarg;
X break;
X default:
X usage:
X fprintf(stderr, "Usage: %s [-h <host>] [-u <user>] [-d <domain>] netgroup\n", argv[0]);
X exit(1);
X }
X if (optind >= argc)
X goto usage;
X for(; optind < argc; optind++) {
X printf("%s: %d\n", argv[optind],
X innetgr(argv[optind], host, user, domain));
X }
X exit(0);
X}
END_OF_FILE
if test 801 -ne `wc -c <'test/innetgr.c'`; then
echo shar: \"'test/innetgr.c'\" unpacked with wrong size!
fi
# end of 'test/innetgr.c'
fi
if test -f 'test/netgroup.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test/netgroup.c'\"
else
echo shar: Extracting \"'test/netgroup.c'\" \(732 characters\)
sed "s/^X//" >'test/netgroup.c' <<'END_OF_FILE'
X/*
X * netgroup - list netgroup members
X * Options:
X * -m - list machine name members (the default)
X * -u - list user names
X * -d - list domain names
X */
X#include <stdio.h>
X
Xmain(argc, argv)
X char **argv;
X{
X char *p[3], *index();
X int i = 0, c;
X extern int optind;
X
X while ((c = getopt(argc, argv, "mud")) != EOF)
X switch (c) {
X case 'm':
X case 'u':
X case 'd':
X p[0] = "mud";
X i = index(p[0], c) - p[0];
X break;
X default:
X usage:
X fprintf(stderr, "Usage: %s [-mud] netgroup\n", argv[0]);
X exit(1);
X }
X if (optind >= argc)
X goto usage;
X for(; optind < argc; optind++) {
X setnetgrent(argv[optind]);
X while (getnetgrent(&p[0], &p[1], &p[2]))
X if (p[i])
X printf("%s\n", p[i]);
X endnetgrent();
X }
X exit(0);
X}
END_OF_FILE
if test 732 -ne `wc -c <'test/netgroup.c'`; then
echo shar: \"'test/netgroup.c'\" unpacked with wrong size!
fi
# end of 'test/netgroup.c'
fi
echo shar: End of shell archive.
exit 0
------------------------------------------------------------------------------