]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZSubs.c
This commit was generated by cvs2svn to compensate for changes in r127,
[1ts-debian.git] / zephyr / lib / ZSubs.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains source for the ZSubscribeTo, ZUnsubscribeTo, and
3  * ZCancelSubscriptions functions.
4  *
5  *      Created by:     Robert French
6  *
7  *      $Id: ZSubs.c,v 1.21 1999/01/22 23:19:30 ghudson Exp $
8  *
9  *      Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h". 
12  */
13
14 #include <internal.h>
15
16 #ifndef lint
17 static const char rcsid_ZSubscriptions_c[] = "$Id: ZSubs.c,v 1.21 1999/01/22 23:19:30 ghudson Exp $";
18 #endif
19
20 static Code_t Z_Subscriptions __P((char *galaxy,
21                                    register ZSubscription_t *sublist,
22                                    int nitems, unsigned int port,
23                                    char *opcode, int authit));
24 static Code_t subscr_sendoff __P((ZNotice_t *notice, char **lyst, int num,
25                                   int authit));
26
27 Code_t ZSubscribeTo(galaxy, sublist, nitems, port)
28     char *galaxy;
29     ZSubscription_t *sublist;
30     int nitems;
31     unsigned int port;
32 {
33     return (Z_Subscriptions(galaxy, sublist, nitems, port,
34                             CLIENT_SUBSCRIBE, 1));
35 }
36
37 Code_t ZSubscribeToSansDefaults(galaxy, sublist, nitems, port)
38     char *galaxy;
39     ZSubscription_t *sublist;
40     int nitems;
41     unsigned int port;
42 {
43     return (Z_Subscriptions(galaxy, sublist, nitems, port,
44                             CLIENT_SUBSCRIBE_NODEFS, 1));
45 }
46
47 Code_t ZUnsubscribeTo(galaxy, sublist, nitems, port)
48     char *galaxy;
49     ZSubscription_t *sublist;
50     int nitems;
51     unsigned int port;
52 {
53     return (Z_Subscriptions(galaxy, sublist, nitems, port,
54                             CLIENT_UNSUBSCRIBE, 1));
55 }
56
57 Code_t ZCancelSubscriptions(galaxy, port)
58     char *galaxy;
59     unsigned int port;
60 {
61     return (Z_Subscriptions(galaxy, (ZSubscription_t *)0, 0, port,
62                             CLIENT_CANCELSUB, 0));
63 }
64
65 /*
66  * This routine must do its own fragmentation.  Subscriptions must
67  * not be broken across packet boundaries, or else the server will
68  * mis-interpret them.
69  */
70
71 static Code_t
72 Z_Subscriptions(galaxy, sublist, nitems, port, opcode, authit)
73     char *galaxy;
74     register ZSubscription_t *sublist;
75     int nitems;
76     unsigned int port;
77     char *opcode;
78     int authit;
79 {
80     register int i, j;
81     int retval;
82     ZNotice_t notice;
83     char header[Z_MAXHEADERLEN];
84     char **list;
85     char *recip;
86     int hdrlen;
87     int size_avail = Z_MAXPKTLEN-Z_FRAGFUDGE; /* space avail for data,
88                                                  adjusted below */
89     int size, start, numok;
90
91     /* nitems = 0 means cancel all subscriptions; still need to allocate a */
92     /* array for one item so we can cancel, however. */
93   
94     list = (char **)malloc((unsigned)((nitems==0)?1:nitems)*3*sizeof(char *));
95     if (!list)
96         return (ENOMEM);
97
98     (void) memset((char *)&notice, 0, sizeof(notice));
99     notice.z_kind = ACKED;
100     notice.z_port = port;
101     notice.z_class = ZEPHYR_CTL_CLASS;
102     notice.z_class_inst = ZEPHYR_CTL_CLIENT;
103     notice.z_opcode = opcode;
104     notice.z_sender = 0;
105     notice.z_recipient = "";
106     notice.z_default_format = "";
107     notice.z_message_len = 0;
108     notice.z_dest_galaxy = galaxy;
109
110     /* format the header to figure out how long it is */
111     retval = Z_FormatHeader(&notice, header, sizeof(header), &hdrlen, ZAUTH);
112     if (retval != ZERR_NONE && !authit)
113         retval = Z_FormatHeader(&notice, header, sizeof(header),
114                                 &hdrlen, ZNOAUTH);
115     if (retval != ZERR_NONE) {
116         free((char *)list);
117         return(retval);
118     }
119
120     /* compute amount of room left */
121     size_avail -= hdrlen;
122     size = size_avail;
123
124     /* assemble subs into an array of pointers */
125     for (i=0;i<nitems;i++) {
126         list[i*3] = sublist[i].zsub_class;
127         list[i*3+1] = sublist[i].zsub_classinst;
128         recip = sublist[i].zsub_recipient;
129         if (recip && *recip == '*')
130             recip++;
131         if (!recip || (*recip != 0 && *recip != '@'))
132             recip = ZGetSender();
133         list[i*3+2] = recip;
134     }
135
136     start = -1;
137     i = 0;
138     numok = 0;
139     if (!nitems) {
140         /* there aren't really any, but we need to xmit anyway */
141         retval = subscr_sendoff(&notice, list, 0, authit);
142         free((char *)list);
143         return(retval);
144     }
145     while(i < nitems) {
146         if (start == -1) {
147             size = size_avail;
148             start = i;
149             numok = 0;
150         }
151         if ((j = strlen(list[i*3])
152              + strlen(list[i*3+1])
153              + strlen(list[i*3+2]) + 3) <= size) {
154             /* it will fit in this packet */
155             size -= j;
156             numok++;
157             i++;
158             continue;
159         }
160         if (!numok) {                   /* a single subscription won't
161                                            fit into one packet */
162             free((char *)list);
163             return(ZERR_FIELDLEN);
164         }
165         retval = subscr_sendoff(&notice, &list[start*3], numok, authit);
166         if (retval) {
167             free((char *)list);
168             return(retval);
169         }
170         start = -1;
171     }
172     if (numok)
173         retval = subscr_sendoff(&notice, &list[start*3], numok, authit);
174     free((char *)list);
175     return(retval);
176 }
177
178 static Code_t
179 subscr_sendoff(notice, lyst, num, authit)
180 ZNotice_t *notice;
181 char **lyst;
182 int num;
183 int authit;
184 {
185     register Code_t retval;
186     ZNotice_t retnotice;
187
188     retval = ZSendList(notice, lyst, num*3, ZAUTH);
189     if (retval != ZERR_NONE && !authit)
190         retval = ZSendList(notice, lyst, num*3, ZNOAUTH);
191         
192     if (retval != ZERR_NONE)
193         return (retval);
194     if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *)0, 
195                                 ZCompareUIDPred, (char *)&notice->z_uid)) !=
196         ZERR_NONE)
197         return (retval);
198     if (retnotice.z_kind == SERVNAK) {
199         ZFreeNotice(&retnotice);
200         return (ZERR_SERVNAK);
201     }
202     if (retnotice.z_kind != SERVACK) {
203         ZFreeNotice(&retnotice);
204         return (ZERR_INTERNAL);
205     }
206     ZFreeNotice(&retnotice);
207     return (ZERR_NONE);
208 }