/*-1* SPDX-License-Identifier: BSD-4-Clause2*3* Copyright (c) 19954* Bill Paul <[email protected]>. All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14* 3. All advertising materials mentioning features or use of this software15* must display the following acknowledgement:16* This product includes software developed by Bill Paul.17* 4. Neither the name of the author nor the names of any co-contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include <stdio.h>35#include <stdlib.h>36#include <string.h>37#include <sys/types.h>38#include "hash.h"3940/*41* This hash function is stolen directly from the42* Berkeley DB package. It already exists inside libc, but43* it's declared static which prevents us from calling it44* from here.45*/46/*47* OZ's original sdbm hash48*/49u_int32_t50hash(const void *keyarg, size_t len)51{52const u_char *key;53size_t loop;54u_int32_t h;5556#define HASHC h = *key++ + 65599 * h5758h = 0;59key = keyarg;60if (len > 0) {61loop = (len + 8 - 1) >> 3;6263switch (len & (8 - 1)) {64case 0:65do {66HASHC;67/* FALLTHROUGH */68case 7:69HASHC;70/* FALLTHROUGH */71case 6:72HASHC;73/* FALLTHROUGH */74case 5:75HASHC;76/* FALLTHROUGH */77case 4:78HASHC;79/* FALLTHROUGH */80case 3:81HASHC;82/* FALLTHROUGH */83case 2:84HASHC;85/* FALLTHROUGH */86case 1:87HASHC;88} while (--loop);89}90}91return (h);92}9394/*95* Generate a hash value for a given key (character string).96* We mask off all but the lower 8 bits since our table array97* can only hold 256 elements.98*/99u_int32_t100hashkey(char *key)101{102103if (key == NULL)104return (-1);105return(hash((void *)key, strlen(key)) & HASH_MASK);106}107108/* Find an entry in the hash table (may be hanging off a linked list). */109char *110lookup(struct group_entry *table[], char *key)111{112struct group_entry *cur;113114cur = table[hashkey(key)];115116while (cur) {117if (!strcmp(cur->key, key))118return(cur->data);119cur = cur->next;120}121122return(NULL);123}124125/*126* Store an entry in the main netgroup hash table. Here's how this127* works: the table can only be so big when we initialize it (TABLESIZE)128* but the number of netgroups in the /etc/netgroup file could easily be129* much larger than the table. Since our hash values are adjusted to130* never be greater than TABLESIZE too, this means it won't be long before131* we find ourselves with two keys that hash to the same value.132*133* One way to deal with this is to malloc(2) a second table and start134* doing indirection, but this is a pain in the butt and it's not worth135* going to all that trouble for a dinky little program like this. Instead,136* we turn each table entry into a linked list and simply link keys137* with the same hash value together at the same index location within138* the table.139*140* That's a lot of comment for such a small piece of code, isn't it.141*/142void143store(struct group_entry *table[], char *key, char *data)144{145struct group_entry *new;146u_int32_t i;147148i = hashkey(key);149150new = (struct group_entry *)malloc(sizeof(struct group_entry));151new->key = strdup(key);152new->data = strdup(data);153new->next = table[i];154table[i] = new;155156return;157}158159/*160* Store a group member entry and/or update its grouplist. This is161* a bit more complicated than the previous function since we have to162* maintain not only the hash table of group members, each group member163* structure also has a linked list of groups hung off it. If handed164* a member name that we haven't encountered before, we have to do165* two things: add that member to the table (possibly hanging them166* off the end of a linked list, as above), and add a group name to167* the member's grouplist list. If we're handed a name that already has168* an entry in the table, then we just have to do one thing, which is169* to update its grouplist.170*/171void172mstore(struct member_entry *table[], char *key, char *data, char *domain)173{174struct member_entry *cur, *new;175struct grouplist *tmp;176u_int32_t i;177178i = hashkey(key);179cur = table[i];180181tmp = (struct grouplist *)malloc(sizeof(struct grouplist));182tmp->groupname = strdup(data);183tmp->next = NULL;184185/* Check if all we have to do is insert a new groupname. */186while (cur) {187if (!strcmp(cur->key, key)) {188tmp->next = cur->groups;189cur->groups = tmp;190return;191}192cur = cur->next;193}194195/* Didn't find a match -- add the whole mess to the table. */196new = (struct member_entry *)malloc(sizeof(struct member_entry));197new->key = strdup(key);198new->domain = domain ? strdup(domain) : "*";199new->groups = tmp;200new->next = table[i];201table[i] = new;202203return;204}205206207