/* This file is part of the Project Athena Zephyr Notification System. * It contains source for the ZSubscribeTo, ZUnsubscribeTo, and * ZCancelSubscriptions functions. * * Created by: Robert French * * $Id$ * * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file * "mit-copyright.h". */ #include #ifndef lint static const char rcsid_ZSubscriptions_c[] = "$Id$"; #endif static Code_t Z_SendAndWaitForServer(ZNotice_t *notice, char *buf, int len, int waitforack); #ifdef CMU_ZCTL_PUNT Code_t ZPunt(ZSubscription_t *sublist, int nitems, unsigned int port) { return (ZSubscriptions(sublist, nitems, port, "SUPPRESS", Z_SendAndWaitForServer)); } #endif Code_t ZSubscribeTo(ZSubscription_t *sublist, int nitems, unsigned int port) { return (ZSubscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE, Z_SendAndWaitForServer)); } Code_t ZSubscribeToSansDefaults(ZSubscription_t *sublist, int nitems, unsigned int port) { return (ZSubscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE_NODEFS, Z_SendAndWaitForServer)); } Code_t ZUnsubscribeTo(ZSubscription_t *sublist, int nitems, unsigned int port) { return (ZSubscriptions(sublist, nitems, port, CLIENT_UNSUBSCRIBE, Z_SendAndWaitForServer)); } Code_t ZCancelSubscriptions(unsigned int port) { return (ZSubscriptions((ZSubscription_t *)0, 0, port, CLIENT_CANCELSUB, Z_SendAndWaitForServer)); } /* * This routine must do its own fragmentation. Subscriptions must * not be broken across packet boundaries, or else the server will * mis-interpret them. */ Code_t ZSubscriptions(register ZSubscription_t *sublist, int nitems, unsigned int port, char *opcode, Code_t (*send_routine)(ZNotice_t *, char *, int, int)) { register int i, j; int retval; ZNotice_t notice; char header[Z_MAXHEADERLEN]; char **list; char *recip; int hdrlen; /* Space available for data, adjusted below. Take off Z_FRAGFUDGE twice. The first is to account for Z_SendFragmentedNotice's space. The second to account for hdrlen not being constant. Zcode escapes bytes 0x00 and 0xFF, so some bytes are encoded as two bytes. */ int size_avail = Z_MAXPKTLEN-Z_FRAGFUDGE-Z_FRAGFUDGE; int size, start, numok; Z_AuthProc cert_routine; /* nitems = 0 means cancel all subscriptions; still need to allocate a */ /* array for one item so we can cancel, however. */ list = (char **)malloc((unsigned)((nitems==0)?1:nitems)*3*sizeof(char *)); if (!list) return (ENOMEM); (void) memset((char *)¬ice, 0, sizeof(notice)); notice.z_kind = ACKED; notice.z_port = port; notice.z_class = ZEPHYR_CTL_CLASS; notice.z_class_inst = ZEPHYR_CTL_CLIENT; notice.z_opcode = opcode; notice.z_sender = 0; notice.z_recipient = ""; notice.z_default_format = ""; notice.z_message_len = 0; /* format the header to figure out how long it is */ retval = Z_FormatHeader(¬ice, header, sizeof(header), &hdrlen, ZAUTH); if (retval != ZERR_NONE) { free((char *)list); return(retval); } /* if a subscription request, we save the key */ if (strcmp(opcode, CLIENT_SUBSCRIBE) == 0 || strcmp(opcode, CLIENT_SUBSCRIBE_NODEFS) == 0) { cert_routine = ZSUBAUTH; } else { cert_routine = ZAUTH; } /* compute amount of room left */ size_avail -= hdrlen; size = size_avail; /* assemble subs into an array of pointers */ for (i=0;iz_multiuid, ¬ice->z_uid)) return (retval); if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *)0, ZCompareUIDPred, (char *)¬ice->z_uid)) != ZERR_NONE) return (retval); if (retnotice.z_kind == SERVNAK) { ZFreeNotice(&retnotice); return (ZERR_SERVNAK); } if (retnotice.z_kind != SERVACK) { ZFreeNotice(&retnotice); return (ZERR_INTERNAL); } ZFreeNotice(&retnotice); return (ZERR_NONE); } Code_t ZFlushUserSubscriptions(char *recip) { register Code_t retval; ZNotice_t notice, retnotice; (void)memset((char *)¬ice, 0, sizeof(notice)); notice.z_kind = ACKED; notice.z_class = ZEPHYR_CTL_CLASS; notice.z_class_inst = ZEPHYR_CTL_CLIENT; notice.z_opcode = CLIENT_FLUSHSUBS; notice.z_recipient = ""; notice.z_default_format = ""; if (recip) { notice.z_message = recip; notice.z_message_len = strlen(recip) + 1; } else { notice.z_message_len = 0; } if ((retval = ZSendNotice(¬ice, ZAUTH)) != ZERR_NONE) return (retval); if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *)0, ZCompareUIDPred, (char *)¬ice.z_uid)) != ZERR_NONE) return (retval); if (retnotice.z_kind == SERVNAK) { ZFreeNotice(&retnotice); return (ZERR_SERVNAK); } if (retnotice.z_kind != SERVACK) { ZFreeNotice(&retnotice); return (ZERR_INTERNAL); } ZFreeNotice(&retnotice); return (ZERR_NONE); }