4ada1e108dde2f1099aa8d51b189639614e2b6a4
[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
10
11 struct CtdlInternalList {
12         struct CtdlInternalList *next;
13         char data[256];
14         };
15
16
17 struct CtdlServerHandle CtdlAppHandle;
18 struct CtdlServInfo CtdlAppServInfo;
19 int CtdlErrno = 0;
20
21 void CtdlMain();
22
23 void logoff(exitcode) {
24         exit(exitcode);
25         }
26
27
28
29 /*
30  * CtdlInternalNumParms()  -  discover number of parameters...
31  */
32 int CtdlInternalNumParms(char *source)
33 {
34         int a;
35         int count = 1;
36
37         for (a=0; a<strlen(source); ++a) 
38                 if (source[a]=='|') ++count;
39         return(count);
40         }
41
42 /*
43  * CtdlInternalExtract()  -  extract a parameter from a series of "|" separated
44  */
45 void CtdlInternalExtract(char *dest, char *source, int parmnum)
46 {
47         char buf[256];
48         int count = 0;
49         int n;
50
51         if (strlen(source)==0) {
52                 strcpy(dest,"");
53                 return;
54                 }
55
56         n = CtdlInternalNumParms(source);
57
58         if (parmnum >= n) {
59                 strcpy(dest,"");
60                 return;
61                 }
62         strcpy(buf,source);
63         if ( (parmnum == 0) && (n == 1) ) {
64                 strcpy(dest,buf);
65                 for (n=0; n<strlen(dest); ++n)
66                         if (dest[n]=='|') dest[n] = 0;
67                 return;
68                 }
69
70         while (count++ < parmnum) do {
71                 strcpy(buf,&buf[1]);
72                 } while( (strlen(buf)>0) && (buf[0]!='|') );
73         if (buf[0]=='|') strcpy(buf,&buf[1]);
74         for (count = 0; count<strlen(buf); ++count)
75                 if (buf[count] == '|') buf[count] = 0;
76         strcpy(dest,buf);
77         }
78
79 /*
80  * CtdlInternalExtractInt()  -  CtdlInternalExtract an int parm w/o supplying a buffer
81  */
82 int CtdlInternalExtractInt(char *source, int parmnum)
83 {
84         char buf[256];
85         
86         CtdlInternalExtract(buf,source,parmnum);
87         return(atoi(buf));
88         }
89
90 /*
91  * CtdlInternalExtractLong()  -  CtdlInternalExtract an long parm w/o supplying a buffer
92  */
93 long CtdlInternalExtractLong(char *source, long int parmnum)
94 {
95         char buf[256];
96         
97         CtdlInternalExtract(buf,source,parmnum);
98         return(atol(buf));
99         }
100
101
102
103
104
105
106
107
108
109
110
111
112 /*
113  * Programs linked against the Citadel server extension library need to
114  * be called with the following arguments:
115  * 0 - program name (as always)
116  * 1 - server address (usually 127.0.0.1)
117  * 2 - server port number
118  * 3 - internal program secret
119  * 4 - user name
120  * 5 - user password
121  * 6 - initial room
122  * 7 - associated client session
123  * 
124  */
125
126 main(argc, argv)
127 int argc;
128 char *argv[]; {
129         int a;
130         char buf[256];
131
132         /* We're really not interested in stdio */
133         close(0);
134         close(1);
135         close(2);
136
137         /* Bail out if someone tries to run this thing manually */
138         if (argc < 3) exit(1);
139
140         /* Zeroing out the server handle neatly sets the values of
141          * CtdlAppHandle to sane default values
142          */
143         bzero(&CtdlAppHandle, sizeof(struct CtdlServerHandle));
144
145         /* Now parse the command-line arguments fed to us by the server */
146         for (a=0; a<argc; ++a) switch(a) {
147                 case 1: strcpy(CtdlAppHandle.ServerAddress, argv[a]);
148                         break;
149                 case 2: CtdlAppHandle.ServerPort = atoi(argv[a]);
150                         break;
151                 case 3: strcpy(CtdlAppHandle.ipgmSecret, argv[a]);
152                         break;
153                 case 4: strcpy(CtdlAppHandle.UserName, argv[a]);
154                         break;
155                 case 5: strcpy(CtdlAppHandle.Password, argv[a]);
156                         break;
157                 case 6: strcpy(CtdlAppHandle.InitialRoom, argv[a]);
158                         break;
159                 case 7: CtdlAppHandle.AssocClientSession = atoi(argv[a]);
160                         break;
161                 }
162
163         /* Connect to the server */
164         argc = 3;
165         attach_to_server(argc, argv);
166         serv_gets(buf);
167         if (buf[0] != '2') exit(1);
168
169         /* Set up the server environment to our liking */
170
171         CtdlInternalGetServInfo(&CtdlAppServInfo, 0);
172
173         sprintf(buf, "IDEN 0|5|006|CitadelAPI Client");
174         serv_puts(buf);
175         serv_gets(buf);
176
177         if (strlen(CtdlAppHandle.ipgmSecret) > 0) {
178                 sprintf(buf, "IPGM %s", CtdlAppHandle.ipgmSecret);
179                 serv_puts(buf);
180                 serv_gets(buf);
181                 }
182
183         if (strlen(CtdlAppHandle.UserName) > 0) {
184                 sprintf(buf, "USER %s", CtdlAppHandle.UserName);
185                 serv_puts(buf);
186                 serv_gets(buf);
187                 sprintf(buf, "PASS %s", CtdlAppHandle.Password);
188                 serv_puts(buf);
189                 serv_gets(buf);
190                 }
191
192         sprintf(buf, "GOTO %s", CtdlAppHandle.InitialRoom);
193         serv_puts(buf);
194         serv_gets(buf);
195         if (buf[0] != '2') {
196                 serv_puts("GOTO _BASEROOM_");
197                 serv_gets(buf);
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() {
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 < 1) || (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         }