1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains source for the ZRetrieveSubscriptions and
3 * ZRetrieveDefaultSubscriptions functions.
4 *
5 * Created by: Robert French
6 *
7 * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
8 * For copying and distribution information, see the file
9 * "mit-copyright.h".
10 */
11
12 #include "internal.h"
13 #include "util.h"
14
15 static Code_t Z_RetSubs(ZNotice_t *notice, int *nsubs, Z_AuthProc auth_routine);
16
17 /* Need STDC definition when possible for unsigned short argument. */
18 #ifdef __STDC__
ZRetrieveSubscriptions(unsigned short port,int * nsubs)19 Code_t ZRetrieveSubscriptions(unsigned short port, int *nsubs)
20 #else
21 Code_t ZRetrieveSubscriptions(port,nsubs)
22 unsigned short port;
23 int *nsubs;
24 #endif
25 {
26 int retval;
27 ZNotice_t notice;
28 char asciiport[50];
29
30 if (!port) /* use default port */
31 port = __Zephyr_port;
32
33 retval = ZMakeAscii16(asciiport, sizeof(asciiport), ntohs(port));
34 if (retval != ZERR_NONE)
35 return (retval);
36
37 (void) memset((char *)¬ice, 0, sizeof(notice));
38 notice.z_message = asciiport;
39 notice.z_message_len = strlen(asciiport)+1;
40 notice.z_opcode = CLIENT_GIMMESUBS;
41
42 return(Z_RetSubs(¬ice, nsubs, ZAUTH));
43 }
44
45 #if 0
46 Code_t ZRetrieveDefaultSubscriptions(nsubs)
47 int *nsubs;
48 {
49 ZNotice_t notice;
50
51 (void) memset((char *)¬ice, 0, sizeof(notice));
52 notice.z_message = (char *) 0;
53 notice.z_message_len = 0;
54 notice.z_opcode = CLIENT_GIMMEDEFS;
55
56 return(Z_RetSubs(¬ice, nsubs, ZNOAUTH));
57
58 }
59 #endif
60
Z_RetSubs(notice,nsubs,auth_routine)61 static Code_t Z_RetSubs(notice, nsubs, auth_routine)
62 register ZNotice_t *notice;
63 int *nsubs;
64 Z_AuthProc auth_routine;
65 {
66 register int i;
67 int retval,nrecv,gimmeack;
68 ZNotice_t retnotice;
69 char *ptr,*end,*ptr2;
70
71 retval = ZFlushSubscriptions();
72
73 if (retval != ZERR_NONE && retval != ZERR_NOSUBSCRIPTIONS)
74 return (retval);
75
76 if (ZGetFD() < 0)
77 if ((retval = ZOpenPort((unsigned short *)0)) != ZERR_NONE)
78 return (retval);
79
80 notice->z_kind = ACKED;
81 notice->z_port = __Zephyr_port;
82 notice->z_class = ZEPHYR_CTL_CLASS;
83 notice->z_class_inst = ZEPHYR_CTL_CLIENT;
84 notice->z_sender = 0;
85 notice->z_recipient = "";
86 notice->z_default_format = "";
87
88 if ((retval = ZSendNotice(notice,auth_routine)) != ZERR_NONE)
89 return (retval);
90
91 nrecv = 0;
92 gimmeack = 0;
93 __subscriptions_list = (ZSubscription_t *) 0;
94
95 while (!nrecv || !gimmeack) {
96 retval = Z_WaitForNotice (&retnotice, ZCompareMultiUIDPred,
97 ¬ice->z_multiuid, SRV_TIMEOUT);
98 if (retval == ZERR_NONOTICE)
99 return ETIMEDOUT;
100 else if (retval != ZERR_NONE)
101 return retval;
102
103 if (retnotice.z_kind == SERVNAK) {
104 ZFreeNotice(&retnotice);
105 return (ZERR_SERVNAK);
106 }
107 /* non-matching protocol version numbers means the
108 server is probably an older version--must punt */
109 if (!purple_strequal(notice->z_version,retnotice.z_version)) {
110 ZFreeNotice(&retnotice);
111 return(ZERR_VERS);
112 }
113 if (retnotice.z_kind == SERVACK &&
114 purple_strequal(retnotice.z_opcode,notice->z_opcode)) {
115 ZFreeNotice(&retnotice);
116 gimmeack = 1;
117 continue;
118 }
119
120 if (retnotice.z_kind != ACKED) {
121 ZFreeNotice(&retnotice);
122 return (ZERR_INTERNAL);
123 }
124
125 nrecv++;
126
127 end = retnotice.z_message+retnotice.z_message_len;
128
129 __subscriptions_num = 0;
130 for (ptr=retnotice.z_message;ptr<end;ptr++)
131 if (!*ptr)
132 __subscriptions_num++;
133
134 __subscriptions_num = __subscriptions_num / 3;
135
136 free(__subscriptions_list);
137 __subscriptions_list = (ZSubscription_t *)
138 malloc((unsigned)(__subscriptions_num*
139 sizeof(ZSubscription_t)));
140 if (__subscriptions_num && !__subscriptions_list) {
141 ZFreeNotice(&retnotice);
142 return (ENOMEM);
143 }
144
145 for (ptr=retnotice.z_message,i = 0; i< __subscriptions_num; i++) {
146 size_t len;
147
148 len = strlen(ptr) + 1;
149 __subscriptions_list[i].zsub_class = (char *)
150 malloc(len);
151 if (!__subscriptions_list[i].zsub_class) {
152 ZFreeNotice(&retnotice);
153 return (ENOMEM);
154 }
155 g_strlcpy(__subscriptions_list[i].zsub_class,ptr,len);
156 ptr += len;
157 len = strlen(ptr) + 1;
158 __subscriptions_list[i].zsub_classinst = (char *)
159 malloc(len);
160 if (!__subscriptions_list[i].zsub_classinst) {
161 ZFreeNotice(&retnotice);
162 return (ENOMEM);
163 }
164 g_strlcpy(__subscriptions_list[i].zsub_classinst,ptr,len);
165 ptr += len;
166 ptr2 = ptr;
167 if (!*ptr2)
168 ptr2 = "*";
169 len = strlen(ptr2) + 1;
170 __subscriptions_list[i].zsub_recipient = (char *)
171 malloc(len);
172 if (!__subscriptions_list[i].zsub_recipient) {
173 ZFreeNotice(&retnotice);
174 return (ENOMEM);
175 }
176 g_strlcpy(__subscriptions_list[i].zsub_recipient,ptr2,len);
177 ptr += strlen(ptr)+1;
178 }
179 ZFreeNotice(&retnotice);
180 }
181
182 __subscriptions_next = 0;
183 *nsubs = __subscriptions_num;
184
185 return (ZERR_NONE);
186 }
187