Home | History | Annotate | Line # | Download | only in revnetgroup
hash.c revision 1.1
      1 /* $OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $ */
      2 /*
      3  * Copyright (c) 1995
      4  *	Bill Paul <wpaul (at) ctr.columbia.edu>.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    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-contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  *
     33  *	$FreeBSD: hash.c,v 1.4 1997/02/22 14:22:01 peter Exp $
     34  */
     35 
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <sys/types.h>
     40 #include "hash.h"
     41 
     42 #ifndef lint
     43 static const char rcsid[] = "$OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $";
     44 #endif
     45 
     46 /*
     47  * This hash function is stolen directly from the
     48  * Berkeley DB package. It already exists inside libc, but
     49  * it's declared static which prevents us from calling it
     50  * from here.
     51  */
     52 /*
     53  * OZ's original sdbm hash
     54  */
     55 u_int32_t
     56 hash(keyarg, len)
     57 	const void *keyarg;
     58 	register size_t len;
     59 {
     60 	register const u_char *key;
     61 	register size_t loop;
     62 	register u_int32_t h;
     63 
     64 #define HASHC   h = *key++ + 65599 * h
     65 
     66 	h = 0;
     67 	key = keyarg;
     68 	if (len > 0) {
     69 		loop = (len + 8 - 1) >> 3;
     70 
     71 		switch (len & (8 - 1)) {
     72 		case 0:
     73 			do {
     74 				HASHC;
     75 				/* FALLTHROUGH */
     76 		case 7:
     77 				HASHC;
     78 				/* FALLTHROUGH */
     79 		case 6:
     80 				HASHC;
     81 				/* FALLTHROUGH */
     82 		case 5:
     83 				HASHC;
     84 				/* FALLTHROUGH */
     85 		case 4:
     86 				HASHC;
     87 				/* FALLTHROUGH */
     88 		case 3:
     89 				HASHC;
     90 				/* FALLTHROUGH */
     91 		case 2:
     92 				HASHC;
     93 				/* FALLTHROUGH */
     94 		case 1:
     95 				HASHC;
     96 			} while (--loop);
     97 		}
     98 	}
     99 	return (h);
    100 }
    101 
    102 /*
    103  * Generate a hash value for a given key (character string).
    104  * We mask off all but the lower 8 bits since our table array
    105  * can only hold 256 elements.
    106  */
    107 u_int32_t hashkey(key)
    108 	char *key;
    109 {
    110 
    111 	if (key == NULL)
    112 		return (-1);
    113 	return(hash((void *)key, strlen(key)) & HASH_MASK);
    114 }
    115 
    116 /* Find an entry in the hash table (may be hanging off a linked list). */
    117 char *lookup(table, key)
    118 	struct group_entry *table[];
    119 	char *key;
    120 {
    121 	struct group_entry *cur;
    122 
    123 	cur = table[hashkey(key)];
    124 
    125 	while (cur) {
    126 		if (!strcmp(cur->key, key))
    127 			return(cur->data);
    128 		cur = cur->next;
    129 	}
    130 
    131 	return(NULL);
    132 }
    133 
    134 /*
    135  * Store an entry in the main netgroup hash table. Here's how this
    136  * works: the table can only be so big when we initialize it (TABLESIZE)
    137  * but the number of netgroups in the /etc/netgroup file could easily be
    138  * much larger than the table. Since our hash values are adjusted to
    139  * never be greater than TABLESIZE too, this means it won't be long before
    140  * we find ourselves with two keys that hash to the same value.
    141  *
    142  * One way to deal with this is to malloc(2) a second table and start
    143  * doing indirection, but this is a pain in the butt and it's not worth
    144  * going to all that trouble for a dinky little program like this. Instead,
    145  * we turn each table entry into a linked list and simply link keys
    146  * with the same hash value together at the same index location within
    147  * the table.
    148  *
    149  * That's a lot of comment for such a small piece of code, isn't it.
    150  */
    151 void store (table, key, data)
    152 	struct group_entry *table[];
    153 	char *key, *data;
    154 {
    155 	struct group_entry *new;
    156 	u_int32_t i;
    157 
    158 	i = hashkey(key);
    159 
    160 	new = (struct group_entry *)malloc(sizeof(struct group_entry));
    161 	new->key = strdup(key);
    162 	new->data = strdup(data);
    163 	new->next = table[i];
    164 	table[i] = new;
    165 
    166 	return;
    167 }
    168 
    169 /*
    170  * Store a group member entry and/or update its grouplist. This is
    171  * a bit more complicated than the previous function since we have to
    172  * maintain not only the hash table of group members, each group member
    173  * structure also has a linked list of groups hung off it. If handed
    174  * a member name that we haven't encountered before, we have to do
    175  * two things: add that member to the table (possibly hanging them
    176  * off the end of a linked list, as above), and add a group name to
    177  * the member's grouplist list. If we're handed a name that already has
    178  * an entry in the table, then we just have to do one thing, which is
    179  * to update its grouplist.
    180  */
    181 void mstore (table, key, data, domain)
    182 	struct member_entry *table[];
    183 	char *key, *data, *domain;
    184 {
    185 	struct member_entry *cur, *new;
    186 	struct grouplist *tmp,*p;
    187 	u_int32_t i;
    188 
    189 	i = hashkey(key);
    190 	cur = table[i];
    191 
    192 	tmp = (struct grouplist *)malloc(sizeof(struct grouplist));
    193 	tmp->groupname = strdup(data);
    194 	tmp->next = NULL;
    195 
    196 	/* Check if all we have to do is insert a new groupname. */
    197 	while (cur) {
    198 		if (!strcmp(cur->key, key) && !strcmp(cur->domain,domain)) {
    199 		  	p = cur->groups;
    200 			while(p) {
    201 				if (!strcmp(p->groupname,data))
    202 					return;
    203 				p = p->next;
    204 			}
    205 			tmp->next = cur->groups;
    206 			cur->groups = tmp;
    207 			return;
    208 		}
    209 		cur = cur->next;
    210 	}
    211 
    212 	/* Didn't find a match -- add the whole mess to the table. */
    213 	new = (struct member_entry *)malloc(sizeof(struct member_entry));
    214 	new->key = strdup(key);
    215 	new->domain = strdup(domain);
    216 	new->groups = tmp;
    217 	new->next = table[i];
    218 	table[i] = new;
    219 
    220 	return;
    221 }
    222