5f01e34f93144338d481a8edaace73a16c0af905
[citadel.git] / citadel / citadelapi.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <time.h>
5 #include <ctype.h>
6 #include <string.h>
7 #include <errno.h>
8 #include "citadel.h"
9 #include "serv_info.h"
10 #include "ipc.h"
11 #include "citadelapi.h"
12
13
14 struct CtdlInternalList {
15         struct CtdlInternalList *next;
16         char data[256];
17         };
18
19
20 struct CtdlServerHandle CtdlAppHandle;
21 struct CtdlServInfo CtdlAppServInfo;
22 struct CtdlRoomInfo CtdlCurrentRoom;
23 int CtdlErrno = 0;
24
25 void logoff(int exitcode) {
26         exit(exitcode);
27         }
28
29
30
31 /*
32  * CtdlInternalNumParms()  -  discover number of parameters...
33  */
34 int CtdlInternalNumParms(char *source)
35 {
36         int a;
37         int count = 1;
38
39         for (a=0; a<strlen(source); ++a) 
40                 if (source[a]=='|') ++count;
41         return(count);
42         }
43
44 /*
45  * CtdlInternalExtract()  -  extract a parameter from a series of "|" separated
46  */
47 void CtdlInternalExtract(char *dest, char *source, int parmnum)
48 {
49         char buf[256];
50         int count = 0;
51         int n;
52
53         if (strlen(source)==0) {
54                 strcpy(dest,"");
55                 return;
56                 }
57
58         n = CtdlInternalNumParms(source);
59
60         if (parmnum >= n) {
61                 strcpy(dest,"");
62                 return;
63                 }
64         strcpy(buf,source);
65         if ( (parmnum == 0) && (n == 1) ) {
66                 strcpy(dest,buf);
67                 for (n=0; n<strlen(dest); ++n)
68                         if (dest[n]=='|') dest[n] = 0;
69                 return;
70                 }
71
72         while (count++ < parmnum) do {
73                 strcpy(buf,&buf[1]);
74                 } while( (strlen(buf)>0) && (buf[0]!='|') );
75         if (buf[0]=='|') strcpy(buf,&buf[1]);
76         for (count = 0; count<strlen(buf); ++count)
77                 if (buf[count] == '|') buf[count] = 0;
78         strcpy(dest,buf);
79         }
80
81 /*
82  * CtdlInternalExtractInt()  -  Extract an int parm w/o supplying a buffer
83  */
84 int CtdlInternalExtractInt(char *source, int parmnum)
85 {
86         char buf[256];
87         
88         CtdlInternalExtract(buf,source,parmnum);
89         return(atoi(buf));
90         }
91
92 /*
93  * CtdlInternalExtractLong()  -  Extract an long parm w/o supplying a buffer
94  */
95 long CtdlInternalExtractLong(char *source, long int parmnum)
96 {
97         char buf[256];
98         
99         CtdlInternalExtract(buf,source,parmnum);
100         return(atol(buf));
101         }
102
103
104
105
106
107
108
109
110
111
112
113
114 /*
115  * Programs linked against the Citadel server extension library need to
116  * be called with the following arguments:
117  * 0 - program name (as always)
118  * 1 - server address (usually 127.0.0.1)
119  * 2 - server port number
120  * 3 - internal program secret
121  * 4 - user name
122  * 5 - user password
123  * 6 - initial room
124  * 7 - associated client session
125  * 
126  */
127
128 int
129 main(int argc, char *argv[])
130 {
131         int a;
132         char buf[256];
133
134         /* We're really not interested in stdio */
135         close(0);
136         close(1);
137         close(2);
138
139         /* Bail out if someone tries to run this thing manually */
140         if (argc < 3) exit(1);
141
142         /* Zeroing out the server handle neatly sets the values of
143          * CtdlAppHandle to sane default values.  This also holds true
144          * for the CtdlCurrentRoom.
145          */
146         bzero(&CtdlAppHandle, sizeof(struct CtdlServerHandle));
147         bzero(&CtdlCurrentRoom, sizeof(struct CtdlRoomInfo));
148
149         /* Now parse the command-line arguments fed to us by the server */
150         for (a=0; a<argc; ++a) switch(a) {
151                 case 1: strcpy(CtdlAppHandle.ServerAddress, argv[a]);
152                         break;
153                 case 2: CtdlAppHandle.ServerPort = atoi(argv[a]);
154                         break;
155                 case 3: strcpy(CtdlAppHandle.ipgmSecret, argv[a]);
156                         break;
157                 case 4: strcpy(CtdlAppHandle.UserName, argv[a]);
158                         break;
159                 case 5: strcpy(CtdlAppHandle.Password, argv[a]);
160                         break;
161                 case 6: strcpy(CtdlAppHandle.InitialRoom, argv[a]);
162                         break;
163                 case 7: CtdlAppHandle.AssocClientSession = atoi(argv[a]);
164                         break;
165                 }
166
167         /* Connect to the server */
168         argc = 3;
169         attach_to_server(argc, argv);
170         serv_gets(buf);
171         if (buf[0] != '2') exit(1);
172
173         /* Set up the server environment to our liking */
174
175         CtdlInternalGetServInfo(&CtdlAppServInfo);
176
177         sprintf(buf, "IDEN 0|5|006|CitadelAPI Client");
178         serv_puts(buf);
179         serv_gets(buf);
180
181         if (strlen(CtdlAppHandle.ipgmSecret) > 0) {
182                 sprintf(buf, "IPGM %s", CtdlAppHandle.ipgmSecret);
183                 serv_puts(buf);
184                 serv_gets(buf);
185                 }
186
187         if (strlen(CtdlAppHandle.UserName) > 0) {
188                 sprintf(buf, "USER %s", CtdlAppHandle.UserName);
189                 serv_puts(buf);
190                 serv_gets(buf);
191                 sprintf(buf, "PASS %s", CtdlAppHandle.Password);
192                 serv_puts(buf);
193                 serv_gets(buf);
194                 }
195
196         if (CtdlGotoRoom(CtdlAppHandle.InitialRoom) != 0) {
197                 CtdlGotoRoom("_BASEROOM_");
198                 }
199
200         /* Now do the loop. */
201         CtdlMain();
202
203         /* Clean up gracefully and exit. */
204         serv_puts("QUIT");
205         exit(0);
206         }
207
208
209 int CtdlGetLastError(void) {
210         return CtdlErrno;
211         }
212
213
214 int CtdlSendExpressMessage(char *ToUser, char *MsgText) {
215         char buf[256];
216
217         if (strlen(ToUser) + strlen(MsgText) > 248) {
218                 CtdlErrno = ERROR + TOO_BIG;
219                 return CtdlErrno;
220                 }
221
222         sprintf(buf, "SEXP %s|%s", ToUser, MsgText);
223         serv_puts(buf);
224         serv_gets(buf);
225         
226         CtdlErrno = atoi(buf);
227         if (CtdlErrno == OK) CtdlErrno = 0;
228         return CtdlErrno;
229         }
230
231
232
233 int CtdlInternalGetUserParam(char *ParamBuf, int ParamNum, char *WhichUser) {
234         char buf[256];
235
236         sprintf(buf, "AGUP %s", WhichUser);
237         serv_puts(buf);
238         serv_gets(buf);
239         if (buf[0] != '2') return(atoi(buf));
240         CtdlInternalExtract(ParamBuf, &buf[4], ParamNum);
241         return(0);
242         }
243
244
245 int CtdlInternalSetUserParam(char *ParamBuf, int ParamNum, char *WhichUser) {
246         char buf[256];
247         char params[8][256];
248         int a;
249
250         sprintf(buf, "AGUP %s", WhichUser);
251         serv_puts(buf);
252         serv_gets(buf);
253         if (buf[0] != '2') return(atoi(buf));
254         for (a=0; a<8; ++a) {
255                 CtdlInternalExtract(&params[a][0], &buf[4], a);
256                 }
257         strcpy(&params[ParamNum][0], ParamBuf);
258         strcpy(buf, "ASUP ");
259         for (a=0; a<8; ++a) {
260                 strcat(buf, &params[a][0]);
261                 strcat(buf, "|");
262                 }
263         serv_puts(buf);
264         serv_gets(buf);
265         if (buf[0] != '2') return(atoi(buf));
266         return(0);
267         }
268
269 /*
270  0 - User name
271  1 - Password
272  2 - Flags (see citadel.h)
273  3 - Times called
274  4 - Messages posted
275  5 - Access level
276  6 - User number
277  7 - Timestamp of last call
278  */
279
280 int CtdlGetUserPassword(char *buf, char *WhichUser) {
281         CtdlErrno = CtdlInternalGetUserParam(buf, 1, WhichUser);
282         return(CtdlErrno);
283         }
284
285 int CtdlSetUserPassword(char *buf, char *WhichUser) {
286         CtdlErrno = CtdlInternalSetUserParam(buf, 1, WhichUser);
287         return(CtdlErrno);
288         }
289
290 unsigned int CtdlGetUserFlags(char *WhichUser) {
291         char buf[256];
292         CtdlErrno = CtdlInternalGetUserParam(buf, 2, WhichUser);
293         return((CtdlErrno == 0) ? atoi(buf) : (-1));
294         }
295
296 int CtdlSetUserFlags(unsigned int NewFlags, char *WhichUser) {
297         char buf[256];
298         sprintf(buf, "%u", NewFlags);
299         CtdlErrno = CtdlInternalGetUserParam(buf, 2, WhichUser);
300         return(CtdlErrno);
301         }
302
303 int CtdlGetUserTimesCalled(char *WhichUser) {
304         char buf[256];
305         CtdlErrno = CtdlInternalGetUserParam(buf, 3, WhichUser);
306         return((CtdlErrno == 0) ? atoi(buf) : (-1));
307         }
308
309 int CtdlSetUserTimesCalled(int NewValue, char *WhichUser) {
310         char buf[256];
311         sprintf(buf, "%d", NewValue);
312         CtdlErrno = CtdlInternalGetUserParam(buf, 3, WhichUser);
313         return(CtdlErrno);
314         }
315
316 int CtdlGetUserMessagesPosted(char *WhichUser) {
317         char buf[256];
318         CtdlErrno = CtdlInternalGetUserParam(buf, 4, WhichUser);
319         return((CtdlErrno == 0) ? atoi(buf) : (-1));
320         }
321
322 int CtdlSetUserMessagesPosted(int NewValue, char *WhichUser) {
323         char buf[256];
324         sprintf(buf, "%d", NewValue);
325         CtdlErrno = CtdlInternalGetUserParam(buf, 4, WhichUser);
326         return(CtdlErrno);
327         }
328
329 int CtdlGetUserAccessLevel(char *WhichUser) {
330         char buf[256];
331         CtdlErrno = CtdlInternalGetUserParam(buf, 5, WhichUser);
332         return((CtdlErrno == 0) ? atoi(buf) : (-1));
333         }
334
335 int CtdlSetUserAccessLevel(int NewValue, char *WhichUser) {
336         char buf[256];
337
338         if ( (NewValue < 0) || (NewValue > 6) ) {
339                 return(ERROR + ILLEGAL_VALUE);
340                 }
341
342         sprintf(buf, "%d", NewValue);
343         CtdlErrno = CtdlInternalGetUserParam(buf, 5, WhichUser);
344         return(CtdlErrno);
345         }
346
347 long CtdlGetUserNumber(char *WhichUser) {
348         char buf[256];
349         CtdlErrno = CtdlInternalGetUserParam(buf, 6, WhichUser);
350         return((CtdlErrno == 0) ? atol(buf) : (-1L));
351         }
352
353 int CtdlSetUserNumber(long NewValue, char *WhichUser) {
354         char buf[256];
355         sprintf(buf, "%ld", NewValue);
356         CtdlErrno = CtdlInternalGetUserParam(buf, 6, WhichUser);
357         return(CtdlErrno);
358         }
359
360 time_t CtdlGetUserLastCall(char *WhichUser) {
361         char buf[256];
362         CtdlErrno = CtdlInternalGetUserParam(buf, 7, WhichUser);
363         return((CtdlErrno == 0) ? atol(buf) : (time_t)(-1L));
364         }
365
366 int CtdlSetUserLastCall(time_t NewValue, char *WhichUser) {
367         char buf[256];
368         sprintf(buf, "%ld", NewValue);
369         CtdlErrno = CtdlInternalGetUserParam(buf, 7, WhichUser);
370         return(CtdlErrno);
371         }
372
373 int CtdlForEachUser(int (*CallBack)(char *EachUser))  {
374         struct CtdlInternalList *TheList = NULL;
375         struct CtdlInternalList *ptr;
376         char buf[256];
377
378         serv_puts("LIST");
379         serv_gets(buf);
380         if (buf[0] != '1') return(-1);
381
382         while (serv_gets(buf), strcmp(buf, "000")) {
383                 ptr = (struct CtdlInternalList *)
384                         malloc(sizeof (struct CtdlInternalList));
385                 if (ptr != NULL) {
386                         CtdlInternalExtract(ptr->data, buf, 0);
387                         ptr->next = TheList;
388                         TheList = ptr;
389                         }
390                 }
391
392         while (TheList != NULL) {
393                 (*CallBack)(TheList->data);
394                 ptr = TheList->next;
395                 free(TheList);
396                 TheList = ptr;
397                 }
398
399         return(0);
400         }
401
402
403
404 /*
405  * Goto a different room
406  */
407 int CtdlGotoRoom(char *RoomName) {
408         char buf[256];
409
410         sprintf(buf, "GOTO %s", RoomName);
411         serv_puts(buf);
412         serv_gets(buf);
413         if (buf[0] != '2') {
414                 CtdlErrno = atoi(buf);
415                 return(CtdlErrno);
416                 }
417         extract(&CtdlCurrentRoom.RoomName, &buf[4], 0);
418         }