From ac16f380e349fa39ec7e26bccb5456cb300006a5 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 14 Sep 1997 17:50:06 +0000 Subject: Pull in sources from zephyr locker. See /mit/zephyr/repository for detailed change information. --- server/class.c | 562 +++++++++++++++++++++++---------------------------------- 1 file changed, 225 insertions(+), 337 deletions(-) (limited to 'server/class.c') diff --git a/server/class.c b/server/class.c index b70bf4e..b4c46d8 100644 --- a/server/class.c +++ b/server/class.c @@ -12,41 +12,40 @@ */ #include +#include "zserver.h" /* includes zephyr/zephyr.h */ +#include #if !defined (lint) && !defined (SABER) -static char rcsid_class_c[] = - "$Id$"; +static const char rcsid_class_c[] = +"$Id$"; #endif -#include "zserver.h" /* includes zephyr/zephyr.h */ - -#include /* for isupper, tolower */ - /* * Class manager subsystem. * * * External functions are: * - * Code_t triplet_register(client, subs) + * Code_t triplet_register(client, subs, realm) * - * Code_t triplet_deregister(client, subs) + * Code_t triplet_deregister(client, subs, realm) * - * ZClientList_t *triplet_lookup(subs) - * ZClient_t *client; - * ZSubscr_t *subs; + * Client *triplet_lookup(subs) + * Client *client; + * Destlist *subs; * - * ZAcl_t *class_get_acl(ZString class_name) + * Acl *class_get_acl(class_name) + * String *class_name; * * Code_t class_restrict(class_name, acl) * char *class_name; - * ZAcl_t *acl; + * Acl *acl; * * Code_t class_setup_restricted(class_name, acl) * char *class_name; - * ZAcl_t *acl; + * Acl *acl; * - * and several ZDestination methods. + * and several Destination methods. */ /* @@ -56,7 +55,7 @@ static char rcsid_class_c[] = * name (which hashes into the bucket associated with this list) and a * doubly linked list of clients which are interested in this class. * The data pointed to by these clients is owned by other modules. Care - * must be taken by the caller not to register a free()'d client + * must be taken by the caller not to a free()'d client * structure. * * If any hash bucket is empty, the pointer is null. @@ -71,26 +70,23 @@ static char rcsid_class_c[] = /* Private variables */ #define EMPTY_CLASS 2000 +#define ALLOC_OFFSET 8 /* Allocate 32 bytes less than a power of 2. */ +#define ALLOC_INIT 8 /* Initial number of subscriptions. */ + #define HASHSIZE 1023 #define HASHVAL(c, i, r) (((c)->hash_val ^ (i)->hash_val ^ (r)->hash_val) \ % HASHSIZE) #define DEST_HASHVAL(dest) HASHVAL((dest).classname, (dest).inst, (dest).recip) -static ZTriplet_t *class_bucket[HASHSIZE]; /* the hash table of pointers */ - +static Triplet *triplet_bucket[HASHSIZE]; /* the hash table of pointers */ -#ifdef __STDC__ -# define P(s) s -#else -# define P(s) () -#endif - -static Code_t remove_client P((ZTriplet_t *ptr, ZClient_t *client)); -static Code_t insert_client P((ZTriplet_t *ptr, ZClient_t *client)); -static ZClientList_t *client_alloc P((ZClient_t *client)); -static ZTriplet_t *triplet_alloc P((ZSTRING *classname, ZSTRING *inst, - ZSTRING *recipient)); -static void free_class P((ZTriplet_t *)); +static Code_t remove_client __P((Triplet *triplet, Client *client, + Realm *realm)); +static Code_t insert_client __P((Triplet *triplet, Client *client, + Realm *realm)); +static Triplet *triplet_alloc __P((String *classname, String *inst, + String *recipient)); +static void free_triplet __P((Triplet *)); /* public routines */ @@ -102,169 +98,112 @@ static void free_class P((ZTriplet_t *)); * been case-sensitive in the recipient string. In most cases, a * failed match will fail on the classname or instance, and a successful * match will succeed on the (d1->recip == d2->recip) check, so this - * shouldn't affect performance. Note that this invalidates the overall - * hash value check, which was of dubious value to start with. + * shouldn't affect performance. */ int ZDest_eq(d1, d2) - ZDestination *d1, *d2; + Destination *d1, *d2; { - return((d1->classname == d2->classname) && - (d1->inst == d2->inst) && - (d1->recip == d2->recip || - strcasecmp(d1->recip->string, d2->recip->string) == 0)); + return((d1->classname == d2->classname) && + (d1->inst == d2->inst) && + (d1->recip == d2->recip || + strcasecmp(d1->recip->string, d2->recip->string) == 0)); } -/* register the client as interested in a triplet */ +/* the client as interested in a triplet */ Code_t -triplet_register(client, dest) - ZClient_t *client; - ZDestination *dest; +triplet_register(client, dest, realm) + Client *client; + Destination *dest; + Realm *realm; { - register ZTriplet_t *ptr, *ptr2; - unsigned long hashval; - - hashval = DEST_HASHVAL(*dest); - - if (!(ptr = class_bucket[hashval])) { - /* not registered */ - - ptr = triplet_alloc(dest->classname, dest->inst, dest->recip); - if (!ptr) - return(ENOMEM); - - /* allocate the head of the bucket */ - - if (!(ptr2 = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t)))) - return(ENOMEM); - - ptr2->zct_clientlist = 0; - ptr2->zct_acl = 0; - ptr2->q_forw = ptr; - ptr2->q_back = ptr; - ptr->q_forw = ptr2; - ptr->q_back = ptr2; - - class_bucket[hashval] = ptr2; - return(insert_client(ptr, client)); - - } else { - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { - /* walk down the list, looking for a match */ - if (ZDest_eq(&ptr2->zct_dest,dest)) - return(insert_client(ptr2, client)); - } + Triplet *triplet; + unsigned long hashval; - /* fell off the end, no match */ - ptr2 = triplet_alloc(dest->classname, dest->inst, dest->recip); - if (!ptr2) - return(ENOMEM); + hashval = DEST_HASHVAL(*dest); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (ZDest_eq(&triplet->dest, dest)) + return insert_client(triplet, client, realm); + } - xinsque(ptr2, ptr); /* insert new class into hash bucket */ - return(insert_client(ptr2, client)); - } + /* Triplet not present in hash table, insert it. */ + triplet = triplet_alloc(dest->classname, dest->inst, dest->recip); + LIST_INSERT(&triplet_bucket[hashval], triplet); + return insert_client(triplet, client, realm); } /* dissociate client from the class, garbage collecting if appropriate */ Code_t -triplet_deregister(client, dest) - ZClient_t *client; - ZDestination *dest; +triplet_deregister(client, dest, realm) + Client *client; + Destination *dest; + Realm *realm; { - register ZTriplet_t *ptr, *ptr2; - int retval = -1; - unsigned long hashval; + Triplet *triplet; + int retval; + unsigned long hashval; - hashval = DEST_HASHVAL(*dest); -#if 0 - zdbug((LOG_DEBUG, "class_dereg: %s %s", dest->classname->string, - dest->inst->string)); -#endif - ptr = class_bucket[hashval]; - if (!ptr) - /* no such class to deregister */ - return(ZSRV_BADASSOC); - - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { - /* walk down the list, looking for a match */ - if (ZDest_eq(&ptr2->zct_dest,dest)) { - retval = remove_client(ptr2, client); - if (retval == EMPTY_CLASS) { #if 0 - zdbug((LOG_DEBUG,"empty class")); + zdbug((LOG_DEBUG, "class_dereg: %s %s", dest->classname->string, + dest->inst->string)); #endif - /* Don't free up restricted classes. */ - if (ptr2->zct_acl) - return(ZERR_NONE); - else { - xremque(ptr2); - free_class(ptr2); - return(ZERR_NONE); - } - } - /* if not EMPTY_CLASS, it's either ZSRV_BADASSOC - (not found) or ZERR_NONE (found and removed), - so break */ - break; - } + hashval = DEST_HASHVAL(*dest); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (ZDest_eq(&triplet->dest, dest)) { + retval = remove_client(triplet, client, realm); + if (retval != ZERR_NONE) + return retval; + if (*triplet->clients == NULL && !triplet->acl) { + LIST_DELETE(triplet); + free_triplet(triplet); + } + return ZERR_NONE; } - - /* fell off: either client not found or client found - and removed, retval contains the result */ - return(retval); + } + return(ZSRV_BADASSOC); } - + /* return a linked list of what clients are interested in this triplet */ -ZClientList_t * +Client ** triplet_lookup(dest) - ZDestination *dest; + Destination *dest; { - register ZTriplet_t *class, *p; - unsigned long hashval; - - hashval = DEST_HASHVAL(*dest); - p = class_bucket[hashval]; - if (p == NULLZT) - return NULLZCLT; - - /* Go search the list for the class */ - for (class = p->q_forw; class != p; class = class->q_forw) { - /* walk down the list, looking for a match */ - if (ZDest_eq(&class->zct_dest,dest)) - return class->zct_clientlist; - } - return NULLZCLT; + Triplet *triplet; + unsigned long hashval; + + hashval = DEST_HASHVAL(*dest); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (ZDest_eq(&triplet->dest, dest)) + return triplet->clients; + } + return NULL; } /* - * return the acl structure associated with class, or NULLZACLT if there is + * return the acl structure associated with class, or NULL if there is * no such acl struct */ -ZAcl_t * +Acl * class_get_acl(class_name) - ZSTRING *class_name; + String *class_name; { - register ZTriplet_t *ptr, *ptr2; - unsigned long hashval; - - hashval = HASHVAL(class_name, empty, empty); - if (!(ptr = class_bucket[hashval])) - return(NULLZACLT); - - /* walk down the list, looking for a match */ - for (ptr2 = ptr->q_back; ptr2 != ptr; ptr2 = ptr2->q_back) - if ((ptr2->zct_dest.classname == class_name) && - (ptr2->zct_dest.inst == empty) && - (ptr2->zct_dest.recip == empty)) - return(ptr2->zct_acl); - - /* fell off the end, no match ==> not restricted */ - return(NULLZACLT); + Triplet *triplet; + unsigned long hashval; + + hashval = HASHVAL(class_name, empty, empty); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (triplet->dest.classname == class_name && + triplet->dest.inst == empty && triplet->dest.recip == empty) + return triplet->acl; + } + + /* No acl found, not restricted. */ + return NULL; } /* @@ -275,35 +214,28 @@ class_get_acl(class_name) Code_t class_restrict(class_name, acl) - char *class_name; - ZAcl_t *acl; + char *class_name; + Acl *acl; { - register ZTriplet_t *ptr, *ptr2; - ZSTRING *d; - unsigned long hashval; - - d = make_zstring(class_name,1); - hashval = HASHVAL(d, empty, empty); - - if (!(ptr = class_bucket[hashval])) { - free_zstring(d); - return(ZSRV_NOCLASS); + Triplet *triplet; + String *d; + unsigned long hashval; + + d = make_string(class_name,1); + hashval = HASHVAL(d, empty, empty); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (triplet->dest.classname == d && triplet->dest.inst == empty && + triplet->dest.recip == empty) { + if (triplet->acl) + return ZSRV_CLASSRESTRICTED; + triplet->acl = acl; + free_string(d); + return ZERR_NONE; } - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) - /* walk down the list, looking for a match */ - if ((ptr2->zct_dest.classname == d) && - (ptr2->zct_dest.inst == empty) && - (ptr2->zct_dest.recip == empty)) { - if (ptr2->zct_acl) - return ZSRV_CLASSRESTRICTED; - ptr2->zct_acl = acl; - free_zstring(d); - return(ZERR_NONE); - } + } - /* fell off the end, no match */ - free_zstring(d); - return(ZSRV_NOCLASS); + free_string(d); + return ZSRV_NOCLASS; } /* @@ -311,132 +243,100 @@ class_restrict(class_name, acl) * structure acl. return ZERR_NONE if no error, or ZSRV_CLASSXISTS * if the class is already registered, or ENOMEM in case of malloc failure. */ - + Code_t class_setup_restricted(class_name, acl) - char *class_name; - ZAcl_t *acl; + char *class_name; + Acl *acl; { - register ZTriplet_t *ptr, *ptr2; - ZSTRING *d; - unsigned long hashval; - - d = make_zstring(class_name,1); - hashval = HASHVAL(d, empty, empty); - - if (!(ptr = class_bucket[hashval])) { - /* not registered */ - - ptr = triplet_alloc(d,empty,empty); - if (!ptr) - return(ENOMEM); - - ptr->zct_acl = acl; - - /* allocate the head of the bucket */ - ptr2 = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t)); - if (!ptr2) - return(ENOMEM); - - ptr2->q_forw = ptr; - ptr2->q_back = ptr; - ptr->q_forw = ptr2; - ptr->q_back = ptr2; - - class_bucket[hashval] = ptr2; - free_zstring(d); - return(ZERR_NONE); - } else { - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) - /* walk down the list, looking for a match */ - if ((ptr2->zct_dest.classname == d) && - (ptr2->zct_dest.inst == empty) && - (ptr2->zct_dest.recip == empty)) { - free_zstring(d); - return(ZSRV_CLASSXISTS); - } - if (!(ptr2 = triplet_alloc(d,empty,empty))) { - free_zstring(d); - return(ENOMEM); - } - - free_zstring(d); - ptr2->zct_acl = acl; - xinsque(ptr2, ptr); - return(ZERR_NONE); + Triplet *triplet; + String *d; + unsigned long hashval; + + d = make_string(class_name,1); + hashval = HASHVAL(d, empty, empty); + for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) { + if (triplet->dest.classname == d && triplet->dest.inst == empty && + triplet->dest.recip == d) { + free_string(d); + return ZSRV_CLASSXISTS; } + } + + /* Triplet not present in hash table, insert it. */ + triplet = triplet_alloc(d, empty, empty); + free_string(d); + if (!triplet) + return ENOMEM; + triplet->acl = acl; + LIST_INSERT(&triplet_bucket[hashval], triplet); + return ZERR_NONE; } /* private routines */ /* allocate space for a class structure */ -static ZTriplet_t * +static Triplet * triplet_alloc(classname,inst,recipient) - ZSTRING *classname; - ZSTRING *inst; - ZSTRING *recipient; + String *classname, *inst, *recipient; { - register ZTriplet_t *ptr; - ZClientList_t *clist; - - if (!(ptr = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t)))) - return(NULLZT); - - ptr->q_forw = ptr->q_back = ptr; - ptr->zct_dest.classname = dup_zstring(classname); - ptr->zct_dest.inst = dup_zstring(inst); - ptr->zct_dest.recip = dup_zstring(recipient); - - if (!(clist = (ZClientList_t *) xmalloc (sizeof (ZClientList_t)))) { - xfree(ptr); - return(NULLZT); - } - clist->q_forw = clist->q_back = clist; - ptr->zct_clientlist = clist; - ptr->zct_acl = NULLZACLT; + Triplet *triplet; + Client *clist; - return (ptr); -} - -/* allocate space for a client entry */ - -static ZClientList_t * -client_alloc(client) - ZClient_t *client; -{ - register ZClientList_t *ptr; - if (!(ptr = (ZClientList_t *) xmalloc(sizeof(ZClientList_t)))) - return(NULLZCLT); + triplet = (Triplet *) malloc(sizeof(Triplet)); + if (!triplet) + return NULL; - ptr->q_forw = ptr->q_back = ptr; - ptr->zclt_client = client; + triplet->dest.classname = dup_string(classname); + triplet->dest.inst = dup_string(inst); + triplet->dest.recip = dup_string(recipient); + triplet->clients = NULL; + triplet->acl = NULL; - return(ptr); + return triplet; } /* insert a client into the list associated with the class *ptr */ static Code_t -insert_client(ptr, client) - ZTriplet_t *ptr; - ZClient_t *client; +insert_client(triplet, client, realm) + Triplet *triplet; + Client *client; + Realm *realm; { - register ZClientList_t *listp, *clist; - - for (clist = ptr->zct_clientlist->q_forw; - clist != ptr->zct_clientlist; - clist = clist->q_forw) { - /* don't duplicate */ - if (clist->zclt_client == client) - return(ZSRV_CLASSXISTS); + Client **clientp, **newclients; + int new_size; + + if (triplet->clients) { + /* Avoid duplication. */ + for (clientp = triplet->clients; *clientp; clientp++) { + if (*clientp == client || (realm && (*clientp)->realm == realm)) + return ZSRV_CLASSXISTS; } - if (!(listp = client_alloc(client))) - return(ENOMEM); + if (clientp + 1 - triplet->clients >= triplet->clients_size) { + new_size = triplet->clients_size * 2 + ALLOC_OFFSET; + newclients = (Client **) realloc(triplet->clients, + new_size * sizeof(Client *)); + if (newclients == NULL) + return ENOMEM; + clientp = newclients + (clientp - triplet->clients); + triplet->clients = newclients; + triplet->clients_size = new_size; + } + } else { + /* Allocate an initial list of client pointers. */ + triplet->clients = (Client **) malloc(ALLOC_INIT * sizeof(Client *)); + if (triplet->clients == NULL) + return ENOMEM; + triplet->clients_size = ALLOC_INIT; + clientp = triplet->clients; + } - xinsque(listp, ptr->zct_clientlist); - return(ZERR_NONE); + *clientp = client; + clientp[1] = NULL; + return ZERR_NONE; } /* @@ -444,70 +344,58 @@ insert_client(ptr, client) * collecting if appropriate */ -static Code_t remove_client(ptr, client) - ZTriplet_t *ptr; - ZClient_t *client; +static Code_t remove_client(triplet, client, realm) + Triplet *triplet; + Client *client; + Realm *realm; { - register ZClientList_t *listp = ptr->zct_clientlist; - register ZClientList_t *listp2; - - if (!listp) - return(ZSRV_BADASSOC); - for (listp2 = listp->q_forw; - listp2 != listp; - listp2 = listp2->q_forw) - /* walk down list, looking for him */ - if (listp2->zclt_client == client) { - xremque(listp2); - xfree(listp2); - if (listp->q_forw == listp) - return(EMPTY_CLASS); - else - return(ZERR_NONE); - } - return(ZSRV_BADASSOC); + Client **clientp; + + for (clientp = triplet->clients; *clientp; clientp++) { + if (*clientp == client || (realm && (*clientp)->realm == realm)) { + for (; *clientp; clientp++) + *clientp = clientp[1]; + return ZERR_NONE; + } + } + + return ZSRV_BADASSOC; } -static void free_class(class) - ZTriplet_t *class; +static void free_triplet(triplet) + Triplet *triplet; { - free_zstring(class->zct_dest.classname); - free_zstring(class->zct_dest.inst); - free_zstring(class->zct_dest.recip); - if (class->zct_acl != NULL) - xfree(class->zct_acl); - if (class->zct_clientlist != NULL) - xfree(class->zct_clientlist); - xfree(class); + if (triplet->clients) + free(triplet->clients); + free_string(triplet->dest.classname); + free_string(triplet->dest.inst); + free_string(triplet->dest.recip); + free(triplet); } - -void class_dump_subs(fp) - register FILE *fp; + +void triplet_dump_subs(fp) + FILE *fp; { int i; - ZTriplet_t *trpq, *trp; - ZClientList_t *cltq, *clt; + Triplet *triplet; + Client **clientp; for (i = 0; i < HASHSIZE; i++) { - trpq = class_bucket[i]; - if (!trpq) - continue; - for (trp = trpq->q_forw; trp != trpq; trp = trp->q_forw) { + for (triplet = triplet_bucket[i]; triplet; triplet = triplet->next) { fputs("Triplet '", fp); - subscr_quote(trp->zct_dest.classname->string, fp); + dump_quote(triplet->dest.classname->string, fp); fputs("' '", fp); - subscr_quote(trp->zct_dest.inst->string, fp); + dump_quote(triplet->dest.inst->string, fp); fputs("' '", fp); - subscr_quote(trp->zct_dest.recip->string, fp); + dump_quote(triplet->dest.recip->string, fp); fputs("':\n", fp); - cltq = trp->zct_clientlist; - if (!cltq) - continue; - for (clt = cltq->q_forw; clt != cltq; clt = clt->q_forw) { - fprintf(fp, "\t%s %d (%s)\n", - inet_ntoa(clt->zclt_client->zct_sin.sin_addr), - ntohs(clt->zclt_client->zct_sin.sin_port), - clt->zclt_client->zct_principal->string); + if (triplet->clients) { + for (clientp = triplet->clients; *clientp; clientp++) { + fprintf(fp, "\t%s %d (%s)\n", + inet_ntoa((*clientp)->addr.sin_addr), + ntohs((*clientp)->addr.sin_port), + (*clientp)->principal->string); + } } } } -- cgit v1.2.3