2 ** libCxClient - Citadel/UX Extensible Client API
3 ** Copyright (c) 2000, Flaming Sword Productions
4 ** Copyright (c) 2001, The Citadel/UX Consortium
9 ** Last Revision: 2000-11-16
10 ** Description: Miscellaneous support functions.
22 ** Function which we have hooked to.
24 static void (*_MiExpFunc)(const char*, const char*) = 0;
27 ** CxRevision(): Report revision information about libCxClient.
30 return(atof(VERSION));
34 ** CxSerialize(): Take a pipe-separated string & convert it into a 2-dimensional
35 ** array. THIS FUNCTION WILL HANDLE AN ABSOLUTE MAXIMUM OF 50 ARGUMENTS.
37 void CxSerialize(const char *s, char **Ser) {
38 char **ap, *argv[50], *end;
41 DPF((DFA,"Serializing '%s'",s));
43 for (ap = argv; (*ap = (char *)strsep(&s, "|")) != NULL;) {
44 if (++ap >= &argv[50]) {
48 end = (char *)(ap - 1);
51 for(ap=&argv[0]; (char *)ap <= end; ap++) {
62 ** CxMiExpSend(): Send an express message. Think of this like AIM
66 ** (char *) user: Username
67 ** (char *) msg: Express message.
71 ** Failure; Unknown Error: 1
73 int CxMiExpSend(const char *user, const char *msg) {
77 DPF((DFA,"Send Express Message"));
78 xmit = (char *)CxMalloc(strlen(user)+strlen(msg) + 7);
79 sprintf(xmit,"SEXP %s|%s",user, msg);
84 if( CHECKRC(rc, RC_OK) ) {
93 ** CxMiExpRecv(): Receive an express message. Usually, this is
94 ** called after a NOOP loop returns RC_xxxx...
97 ** Success: Ptr to malloc()ed message text. [*]
100 char *CxMiExpRecv() {
101 char buf[255], *toret;
104 DPF((DFA,"Receive Express Message"));
107 DPF((DFA,"buf=%s\n",buf));
109 DPF((DFA,"Checking result = ", rc));
110 if( CHECKRC(rc, RC_LISTING)) {
111 DPF((DFA,"Preparing to return"));
112 toret = (char *) CxMalloc(strlen(buf)+2);
116 if((rc = CxClRecv(buf))) {
118 toret = (char *) realloc(toret, strlen(toret)+strlen(buf)+1);
124 DPF((DFA," toret = %s", toret));
130 ** CxMiExpCheck(): Check to see if there are any EXPress MEssages
131 ** waiting for the currently logged-in user.
134 ** Message Waiting: 1
141 DPF((DFA,"Sending NOOP"));
143 DPF((DFA,"Checking response"));
147 ** CxClRecv() tacks on a RC_MESGWAIT flag to the result
148 ** code upon seeing a Message Waiting note from the
149 ** server. This behaviour is deprecated in updated
150 ** versions of Citadel/UX, but is still included for
151 ** compatibility's sake.
153 if(CHECKRC(rc,RC_MESGWAIT)) {
154 DPF((DFA,"Express Message waiting!"));
158 DPF((DFA,"No express message, loser."));
164 ** _CxMiExpHook(): Hook to RC_901 messages [Contain express messages]
165 ** [Not Intended For External Use]
168 void _CxMiExpHook(const void* data) {
169 char buf[512], *user_buf, *data_buf;
172 DPF((DFA, "Received RC_901 message"));
173 DPF((DFA, "Raw data: %s\n", (char *)data));
176 user_buf = (char *)CxMalloc(strlen(buf)+1);
177 strcpy(user_buf, buf);
179 data_buf = (char *)CxMalloc(1);
183 ** If this is a multi-line message:
185 if(CHECKRC(rc, RC_LISTING)) {
189 realloc(data_buf, strlen(data_buf)+strlen(buf));
190 strcat(data_buf, buf);
194 _MiExpFunc(user_buf, data_buf);
200 ** CxMiExpHook(): We will allow the user to hook themselves into
201 ** our express message handler. Only one function is permitted to
205 ** func: The function that the user has written to handle Express
207 ** void func( const char *USER_FROM, const char *TEXT);
209 void CxMiExpHook(void (*func)(const char*, const char *)) {
211 DPF((DFA, "Hooking user func@0x%08x",func));
214 ** If libCxClient has not already hooked this type of
215 ** message, we need to go ahead and hook it to our
216 ** internal routing function.
218 if(!CxClCbExists(901)) {
219 DPF((DFA, "Hooking into RC_901"));
220 CxClCbRegister(901, _CxMiExpHook);
224 ** Now, register the user's hooked function with
225 ** ourselves. This instructs _CxMiExpHook() on
226 ** where to route data.
228 DPF((DFA,"Registering user hook"));
231 DPF((DFA,"Ok, at this point, RC_901 messages should be routed to the user."));
232 DPF((DFA,"Don't blame me if it doesn't work. You told me what to do, Brian."));
236 ** CxMiMessage(): Read a system message file, ONE LINE AT A TIME.
237 ** This function will return the current line sent by the server,
238 ** and will return NULL on completion. The caller is responsible
239 ** for freeing EACH LINE OF MEMORY passed to it.
242 ** (char *)file: The name of the file we want, or NULL to continue
243 ** the current stream...
246 ** Success: Ptr to malloc()ed file data. [*]
247 ** Failure; File not found: NULL
249 char *CxMiMessage(const char *file) {
250 char buf[255], *toret;
253 if((file!=NULL) && file[0]) {
254 DPF((DFA,"Requesting %s from server.",file));
255 sprintf(buf,"MESG %s", file);
258 if(CHECKRC(rc, RC_LISTING)) {
259 DPF((DFA,"Retrieving line from file..."));
262 toret = (char *)CxMalloc(strlen(buf)+1);
264 DPF((DFA,"MEM/MDA:\t-1\t@0x%08x (Needs manual deallocation)", toret));
274 DPF((DFA,"Retrieving line from file..."));
277 toret = (char *)CxMalloc(strlen(buf)+1);
279 DPF((DFA,"MEM/MDA:\t-1\t@0x%08x (Needs manual deallocation)", toret));
287 ** Insurance measure...
293 ** CxMiImage(): Read a system image. Images are defined by the
294 ** Citadel/UX session protocol manual as always being in GIF
298 ** (char *)img: Name of the image we are requesting.
301 ** Success: Ptr to malloc()ed image data. [*]
302 ** Failure; File not found: NULL
304 char *CxMiImage(const char *img) {
307 ** Hmm.. Not sure how similar this is to MESG...
308 ** Will defer this code until I can reference the