diff options
author | John Kohl <jtkohl@mit.edu> | 1987-06-19 06:29:53 +0000 |
---|---|---|
committer | John Kohl <jtkohl@mit.edu> | 1987-06-19 06:29:53 +0000 |
commit | ff687ceff9d00d35f0d9df0c86f2fee5b111059d (patch) | |
tree | 7066993d388bfa4280008eed76228354da7a5792 /server/subscr.c | |
parent | 0543936bef46ef47a12601373a1cf16f0301d808 (diff) |
Initial revision
Diffstat (limited to 'server/subscr.c')
-rw-r--r-- | server/subscr.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/server/subscr.c b/server/subscr.c new file mode 100644 index 0000000..2036f47 --- /dev/null +++ b/server/subscr.c @@ -0,0 +1,389 @@ +/* This file is part of the Project Athena Zephyr Notification System. + * It contains functions for managing subscription lists. + * + * Created by: John T. Kohl + * + * $Source$ + * $Author$ + * + * Copyright (c) 1987 by the Massachusetts Institute of Technology. + * For copying and distribution information, see the file + * "mit-copyright.h". + */ + +#include <zephyr/mit-copyright.h> + +#ifndef lint +static char rcsid_subscr_s_c[] = "$Header$"; +#endif lint + +/* + * The subscription manager. + * + * External functions: + * + * Code_t subscr_subscribe(notice) + * ZNotice_t *notice; + * + * Code_t subscr_cancel(notice) + * ZNotice_t *notice; + * + * Code_t subscr_cancel_client(client) + * ZClient_t *client; + * + * Code_t subscr_cancel_host(addr) + * struct in_addr *addr; + * + * ZClientList_t *subscr_match_list(notice) + * ZNotice_t *notice; + * + * void subscr_list_free(list) + * ZClientList_t *list; + * + */ + +#include "zserver.h" + +extern char *re_comp(), *rindex(), *index(); +static ZSubscr_t *extract_subscriptions(); +static int subscr_equiv(); +static void free_subscriptions(), free_sub(); + +Code_t +subscr_subscribe(notice) +ZNotice_t *notice; +{ + ZClient_t *who; + register ZSubscr_t *subs, *subs2, *newsubs, *subs3; + Code_t retval; + + if ((who = client_which_client(notice)) == NULLZCNT) + return(ZSRV_NOCLT); + + if (who->zct_subs == NULLZST) { + /* allocate a subscription head */ + if ((subs = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) + return(ENOMEM); + subs->q_forw = subs->q_back = subs; + who->zct_subs = subs; + } + + if ((newsubs = extract_subscriptions(notice)) == NULLZST) + return(ZERR_NONE); /* no subscr -> no error */ + + for (subs = newsubs->q_forw; + subs != newsubs; + subs = subs->q_forw) { + /* for each new subscription */ + + for (subs2 = who->zct_subs->q_forw; + subs2 != who->zct_subs; + subs2 = subs2->q_forw) { + /* for each existing subscription */ + if (subscr_equiv(subs, subs2)) /* duplicate? */ + goto duplicate; + } + + /* ok, we are a new subscription. register and chain on. */ + + if ((subs3 = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) { + free_subscriptions(newsubs); + return(ENOMEM); + } + + if ((retval = class_register(who, subs->zst_class)) != ZERR_NONE) { + free_subscriptions(newsubs); + return(retval); + } + + subs3->zst_class = strsave(subs->zst_class); + subs3->zst_classinst = strsave(subs->zst_classinst); + subs3->zst_recipient = strsave(subs->zst_recipient); + + insque(who->zct_subs, subs3); + +duplicate: ; /* just go on to the next */ + } + + free_subscriptions(newsubs); + return(ZERR_NONE); +} + +/* are the subscriptions the same? 1=yes, 0=no */ + +static int +subscr_equiv(s1, s2) +register ZSubscr_t *s1, *s2; +{ + if (strcmp(s1->zst_class,s2->zst_class)) + return(0); + if (strcmp(s1->zst_classinst,s2->zst_classinst)) + return(0); + if (strcmp(s1->zst_recipient,s2->zst_recipient)) + return(0); + return(1); +} + +static ZSubscr_t * +extract_subscriptions(notice) +register ZNotice_t *notice; +{ + register ZSubscr_t *subs = NULLZST, *subs2; + register int len = notice->z_message_len; + register char *recip, *class, *classinst; + register char *cp = notice->z_message; + char *buf; + + /* parse the data area for the subscriptions */ + while (cp < notice->z_message + notice->z_message_len) { + recip = buf = cp; + if ((cp = index(buf, ',')) == NULL) { + syslog(LOG_WARNING, "malformed subscription 1 %s", + buf); + return(subs); + } + *cp++ = '\0'; + class = buf = cp; + if ((cp = index(buf, ',')) == NULL) { + syslog(LOG_WARNING, "malformed subscription 2 %s", + buf); + return(subs); + } + *cp++ = '\0'; + classinst = cp; + cp += strlen(classinst); + if (subs == NULLZST) { + if ((subs = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) { + syslog(LOG_WARNING, "ex_subs: no mem"); + return(NULLZST); + } + subs->q_forw = subs->q_back = subs; + } + if ((subs2 = (ZSubscr_t *) malloc(sizeof(ZSubscr_t))) == NULLZST) { + syslog(LOG_WARNING, "ex_subs: no mem 2"); + return(NULLZST); + } + subs2->zst_class = strsave(class); + subs2->zst_classinst = strsave(classinst); + subs2->zst_recipient = strsave(recip); + + insque(subs, subs2); + } + return; +} + +static void +free_subscriptions(subs) +register ZSubscr_t *subs; +{ + register ZSubscr_t *sub; + + free(subs->zst_class); + free(subs->zst_classinst); + free(subs->zst_recipient); + + for (sub = subs->q_forw; sub != subs; sub = subs->q_forw) { + free(sub->zst_class); + free(sub->zst_classinst); + free(sub->zst_recipient); + remque(sub); + free(sub); + } + free(subs); + return; +} + +Code_t +subscr_cancel(notice) +ZNotice_t *notice; +{ + ZClient_t *who; + register ZSubscr_t *subs, *subs2; + Code_t retval; + + if ((who = client_which_client(notice)) == NULLZCNT) + return(ZSRV_NOCLT); + + if (who->zct_subs == NULLZST) + return(ZSRV_NOSUB); + + if ((subs = extract_subscriptions(notice)) == NULLZST) + return(ZERR_NONE); /* no subscr -> no error */ + + for (subs2 = who->zct_subs->q_forw; + subs2 != who->zct_subs; + subs2 = subs2->q_forw) { + /* for each existing subscription */ + if (subscr_equiv(subs, subs2)) { /* duplicate? */ + remque(subs2); + if (class_deregister(who, subs2->zst_class) != ZERR_NONE) { + syslog(LOG_ERR, "subscr_cancel: not registered!"); + abort(); + /*NOTREACHED*/ + } + free_sub(subs2); + return(ZERR_NONE); + } + } + return(ZSRV_NOSUB); +} + +static void +free_sub(sub) +ZSubscr_t *sub; +{ + free(sub->zst_class); + free(sub->zst_classinst); + free(sub->zst_recipient); + free(sub); + return; +} + +Code_t +subscr_cancel_client(client) +register ZClient_t *client; +{ + register ZSubscr_t *subs; + + if (client->zct_subs == NULLZST) + return(ZERR_NONE); + + for (subs = client->zct_subs->q_forw; + subs != client->zct_subs; + subs = client->zct_subs->q_forw) { + if (class_deregister(client, subs->zst_class) != ZERR_NONE) { + syslog(LOG_ERR, "sub_can_clt: not registered!"); + abort(); + /*NOTREACHED*/ + } + remque(subs); + free_sub(subs); + } + return(ZERR_NONE); +} + +Code_t +subscr_cancel_host(addr, server) +struct in_addr *addr; +ZServerDesc_t *server; +{ + register ZHostList_t *hosts; + register ZClientList_t *clist = NULLZCLT, *clt; + + /* find list of clients */ + for (hosts = server->zs_hosts; + hosts != server->zs_hosts; + hosts = hosts->q_forw) { + if (!bcmp(*addr, hosts->zh_addr, sizeof (struct in_addr))) { + clist = hosts->zh_clients; + break; + } + } + if (hosts != server->zs_hosts) + return(ZSRV_WRONGSRV); + + /* flush each one */ + for (clt = clist->q_forw; clt != clist; clt = clt->q_forw) + (void) subscr_cancel_client(clt); + return(ZERR_NONE); +} + +/* + * Here is the bulk of the work in the subscription manager. + * We grovel over the list of clients possibly interested in this + * notice, and copy into a list on a match. + */ + +ZClientList_t * +subscr_match_list(notice) +ZNotice_t *notice; +{ + register ZClientList_t *hits, *clients, *clients2, *hit2; + + if ((hits = (ZClientList_t *) malloc(sizeof(ZClientList_t))) == NULLZCLT) + return(NULLZCLT); + hits->q_forw = hits->q_back = hits; + + if ((clients = class_lookup(notice->z_class)) == NULLZCLT) + return(NULLZCLT); + + for (clients2 = clients->q_forw; + clients2 != clients; + clients2 = clients2->q_forw) + if (client_match(notice, clients2->zclt_client)) { + /* we hit */ + if ((hit2 = (ZClientList_t *) malloc(sizeof(ZClientList_t))) == NULLZCLT) { + syslog(LOG_WARNING, "subscr_match: punting/no mem"); + return(hits); + } + hit2->zclt_client = clients2->zclt_client; + insque(hits, hit2); + } + + + if (hits->q_forw == hits) + return(NULLZCLT); + return(hits); +} + +void +subscr_list_free(list) +ZClientList_t *list; +{ + register ZClientList_t *lyst; + + for (lyst = list->q_forw; lyst != list; lyst = list->q_forw) { + remque(lyst); + free(lyst); + } + free(list); + return; +} + +#define ZCLASS_MATCHALL "ZMATCH_ALL" +/* + * is this client listening to this notice? 1=yes, 0=no + */ +static int +client_match(notice, client) +register ZNotice_t *notice; +register ZClient_t *client; +{ + register ZSubscr_t *subs; + char *reresult; + + if (client->zct_subs == NULLZST) { + syslog(LOG_WARNING, "client_match w/ no subs"); + return(0); + } + + for (subs = client->zct_subs->q_forw; + subs != client->zct_subs; + subs = subs->q_forw) { + /* for each subscription, do regex matching */ + /* we don't regex the class, since wildcard + matching on the class is disallowed. However, + we do check for the Magic Class */ + if (strcmp(ZCLASS_MATCHALL, subs->zst_class) && + strcmp(notice->z_class, subs->zst_class)) + continue; /* no match */ + if ((reresult = re_comp(subs->zst_classinst)) != NULL) { + syslog(LOG_WARNING, "re_comp error %s on '%s'", + reresult, subs->zst_classinst); + continue; + } + if (!re_exec(notice->z_class_inst)) + continue; + if ((reresult = re_comp(subs->zst_recipient)) != NULL) { + syslog(LOG_WARNING, "re_comp error %s on '%s'", + reresult, subs->zst_recipient); + continue; + } + if (!re_exec(notice->z_recipient)) + continue; + /* OK, we matched */ + return(1); + } + /* fall through */ + return(0); +} |