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 *)&notice, 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(&notice, 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 *)&notice, 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(&notice, 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 					  &notice->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