bad2a68d3ab893c4765d66f77af0072fe5df6fd6
[citadel.git] / citadel / control.c
1 /*
2  * $Id$
3  *
4  * This module handles states which are global to the entire server.
5  *
6  */
7
8 #ifdef DLL_EXPORT
9 #define IN_LIBCIT
10 #endif
11
12 #include "sysdep.h"
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <fcntl.h>
17 #include <signal.h>
18
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
21 # include <time.h>
22 #else
23 # if HAVE_SYS_TIME_H
24 #  include <sys/time.h>
25 # else
26 #  include <time.h>
27 # endif
28 #endif
29
30 #include <ctype.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <sys/types.h>
35 #include "citadel.h"
36 #include "server.h"
37 #include "control.h"
38 #include "serv_extensions.h"
39 #include "sysdep_decls.h"
40 #include "support.h"
41 #include "config.h"
42 #include "msgbase.h"
43 #include "citserver.h"
44 #include "tools.h"
45 #include "room_ops.h"
46
47 #ifndef HAVE_SNPRINTF
48 #include "snprintf.h"
49 #endif
50
51 struct CitControl CitControl;
52 extern struct config config;
53 FILE *control_fp = NULL;
54
55 /*
56  * get_control  -  read the control record into memory.
57  */
58 void get_control(void)
59 {
60
61         /* Zero it out.  If the control record on disk is missing or short,
62          * the system functions with all control record fields initialized
63          * to zero.
64          */
65         memset(&CitControl, 0, sizeof(struct CitControl));
66         if (control_fp == NULL) {
67                 control_fp = fopen(
68 #ifndef HAVE_RUN_DIR
69                                                    "."
70 #else
71                                                    RUN_DIR
72 #endif
73                                                    "/citadel.control", "rb+");
74                 if (control_fp != NULL) {
75                         fchown(fileno(control_fp), config.c_ctdluid, -1);
76                 }
77         }
78         if (control_fp == NULL) {
79                 control_fp = fopen(
80 #ifndef HAVE_RUN_DIR
81                                                    "."
82 #else
83                                                    RUN_DIR
84 #endif
85                                                    "/citadel.control", "wb+");
86                 if (control_fp != NULL) {
87                         fchown(fileno(control_fp), config.c_ctdluid, -1);
88                         memset(&CitControl, 0, sizeof(struct CitControl));
89                         fwrite(&CitControl, sizeof(struct CitControl),
90                                1, control_fp);
91                         rewind(control_fp);
92                 }
93         }
94         if (control_fp == NULL) {
95                 lprintf(CTDL_ALERT, "ERROR opening citadel.control: %s\n",
96                         strerror(errno));
97                 return;
98         }
99
100         rewind(control_fp);
101         fread(&CitControl, sizeof(struct CitControl), 1, control_fp);
102 }
103
104 /*
105  * put_control  -  write the control record to disk.
106  */
107 void put_control(void)
108 {
109
110         if (control_fp != NULL) {
111                 rewind(control_fp);
112                 fwrite(&CitControl, sizeof(struct CitControl), 1,
113                        control_fp);
114                 fflush(control_fp);
115         }
116 }
117
118
119 /*
120  * get_new_message_number()  -  Obtain a new, unique ID to be used for a message.
121  */
122 long get_new_message_number(void)
123 {
124         begin_critical_section(S_CONTROL);
125         get_control();
126         ++CitControl.MMhighest;
127         put_control();
128         end_critical_section(S_CONTROL);
129         return (CitControl.MMhighest);
130 }
131
132
133 /*
134  * get_new_user_number()  -  Obtain a new, unique ID to be used for a user.
135  */
136 long get_new_user_number(void)
137 {
138         begin_critical_section(S_CONTROL);
139         get_control();
140         ++CitControl.MMnextuser;
141         put_control();
142         end_critical_section(S_CONTROL);
143         return (CitControl.MMnextuser);
144 }
145
146
147
148 /*
149  * get_new_room_number()  -  Obtain a new, unique ID to be used for a room.
150  */
151 long get_new_room_number(void)
152 {
153         begin_critical_section(S_CONTROL);
154         get_control();
155         ++CitControl.MMnextroom;
156         put_control();
157         end_critical_section(S_CONTROL);
158         return (CitControl.MMnextroom);
159 }
160
161
162
163 /* 
164  * Get or set global configuration options
165  */
166 void cmd_conf(char *argbuf)
167 {
168         char cmd[16];
169         char buf[256];
170         int a;
171         char *confptr;
172         char confname[128];
173
174         if (CtdlAccessCheck(ac_aide)) return;
175
176         extract_token(cmd, argbuf, 0, '|', sizeof cmd);
177         if (!strcasecmp(cmd, "GET")) {
178                 cprintf("%d Configuration...\n", LISTING_FOLLOWS);
179                 cprintf("%s\n", config.c_nodename);
180                 cprintf("%s\n", config.c_fqdn);
181                 cprintf("%s\n", config.c_humannode);
182                 cprintf("%s\n", config.c_phonenum);
183                 cprintf("%d\n", config.c_creataide);
184                 cprintf("%d\n", config.c_sleeping);
185                 cprintf("%d\n", config.c_initax);
186                 cprintf("%d\n", config.c_regiscall);
187                 cprintf("%d\n", config.c_twitdetect);
188                 cprintf("%s\n", config.c_twitroom);
189                 cprintf("%s\n", config.c_moreprompt);
190                 cprintf("%d\n", config.c_restrict);
191                 cprintf("%s\n", config.c_site_location);
192                 cprintf("%s\n", config.c_sysadm);
193                 cprintf("%d\n", config.c_maxsessions);
194                 cprintf("xxx\n"); /* placeholder -- field no longer in use */
195                 cprintf("%d\n", config.c_userpurge);
196                 cprintf("%d\n", config.c_roompurge);
197                 cprintf("%s\n", config.c_logpages);
198                 cprintf("%d\n", config.c_createax);
199                 cprintf("%ld\n", config.c_maxmsglen);
200                 cprintf("%d\n", config.c_min_workers);
201                 cprintf("%d\n", config.c_max_workers);
202                 cprintf("%d\n", config.c_pop3_port);
203                 cprintf("%d\n", config.c_smtp_port);
204                 cprintf("%d\n", config.c_rfc822_strict_from);
205                 cprintf("%d\n", config.c_aide_zap);
206                 cprintf("%d\n", config.c_imap_port);
207                 cprintf("%ld\n", config.c_net_freq);
208                 cprintf("%d\n", config.c_disable_newu);
209                 cprintf("1\n"); /* niu */
210                 cprintf("%d\n", config.c_purge_hour);
211 #ifdef HAVE_LDAP
212                 cprintf("%s\n", config.c_ldap_host);
213                 cprintf("%d\n", config.c_ldap_port);
214                 cprintf("%s\n", config.c_ldap_base_dn);
215                 cprintf("%s\n", config.c_ldap_bind_dn);
216                 cprintf("%s\n", config.c_ldap_bind_pw);
217 #else
218                 cprintf("\n");
219                 cprintf("0\n");
220                 cprintf("\n");
221                 cprintf("\n");
222                 cprintf("\n");
223 #endif
224                 cprintf("%s\n", config.c_ip_addr);
225                 cprintf("%d\n", config.c_msa_port);
226                 cprintf("%d\n", config.c_imaps_port);
227                 cprintf("%d\n", config.c_pop3s_port);
228                 cprintf("%d\n", config.c_smtps_port);
229                 cprintf("%d\n", config.c_enable_fulltext);
230                 cprintf("%d\n", config.c_auto_cull);
231                 cprintf("000\n");
232         }
233
234         else if (!strcasecmp(cmd, "SET")) {
235                 unbuffer_output();
236                 cprintf("%d Send configuration...\n", SEND_LISTING);
237                 a = 0;
238                 while (client_getln(buf, sizeof buf), strcmp(buf, "000")) {
239                         switch (a) {
240                         case 0:
241                                 safestrncpy(config.c_nodename, buf,
242                                             sizeof config.c_nodename);
243                                 break;
244                         case 1:
245                                 safestrncpy(config.c_fqdn, buf,
246                                             sizeof config.c_fqdn);
247                                 break;
248                         case 2:
249                                 safestrncpy(config.c_humannode, buf,
250                                             sizeof config.c_humannode);
251                                 break;
252                         case 3:
253                                 safestrncpy(config.c_phonenum, buf,
254                                             sizeof config.c_phonenum);
255                                 break;
256                         case 4:
257                                 config.c_creataide = atoi(buf);
258                                 break;
259                         case 5:
260                                 config.c_sleeping = atoi(buf);
261                                 break;
262                         case 6:
263                                 config.c_initax = atoi(buf);
264                                 if (config.c_initax < 1)
265                                         config.c_initax = 1;
266                                 if (config.c_initax > 6)
267                                         config.c_initax = 6;
268                                 break;
269                         case 7:
270                                 config.c_regiscall = atoi(buf);
271                                 if (config.c_regiscall != 0)
272                                         config.c_regiscall = 1;
273                                 break;
274                         case 8:
275                                 config.c_twitdetect = atoi(buf);
276                                 if (config.c_twitdetect != 0)
277                                         config.c_twitdetect = 1;
278                                 break;
279                         case 9:
280                                 safestrncpy(config.c_twitroom, buf,
281                                             sizeof config.c_twitroom);
282                                 break;
283                         case 10:
284                                 safestrncpy(config.c_moreprompt, buf,
285                                             sizeof config.c_moreprompt);
286                                 break;
287                         case 11:
288                                 config.c_restrict = atoi(buf);
289                                 if (config.c_restrict != 0)
290                                         config.c_restrict = 1;
291                                 break;
292                         case 12:
293                                 safestrncpy(config.c_site_location, buf,
294                                             sizeof config.c_site_location);
295                                 break;
296                         case 13:
297                                 safestrncpy(config.c_sysadm, buf,
298                                             sizeof config.c_sysadm);
299                                 break;
300                         case 14:
301                                 config.c_maxsessions = atoi(buf);
302                                 if (config.c_maxsessions < 0)
303                                         config.c_maxsessions = 0;
304                                 break;
305                         case 15:
306                                 /* placeholder -- field no longer in use */
307                                 break;
308                         case 16:
309                                 config.c_userpurge = atoi(buf);
310                                 break;
311                         case 17:
312                                 config.c_roompurge = atoi(buf);
313                                 break;
314                         case 18:
315                                 safestrncpy(config.c_logpages, buf,
316                                             sizeof config.c_logpages);
317                                 break;
318                         case 19:
319                                 config.c_createax = atoi(buf);
320                                 if (config.c_createax < 1)
321                                         config.c_createax = 1;
322                                 if (config.c_createax > 6)
323                                         config.c_createax = 6;
324                                 break;
325                         case 20:
326                                 if (atoi(buf) >= 8192)
327                                         config.c_maxmsglen = atoi(buf);
328                                 break;
329                         case 21:
330                                 if (atoi(buf) >= 2)
331                                         config.c_min_workers = atoi(buf);
332                         case 22:
333                                 if (atoi(buf) >= config.c_min_workers)
334                                         config.c_max_workers = atoi(buf);
335                         case 23:
336                                 config.c_pop3_port = atoi(buf);
337                                 break;
338                         case 24:
339                                 config.c_smtp_port = atoi(buf);
340                                 break;
341                         case 25:
342                                 config.c_rfc822_strict_from = atoi(buf);
343                                 break;
344                         case 26:
345                                 config.c_aide_zap = atoi(buf);
346                                 if (config.c_aide_zap != 0)
347                                         config.c_aide_zap = 1;
348                                 break;
349                         case 27:
350                                 config.c_imap_port = atoi(buf);
351                                 break;
352                         case 28:
353                                 config.c_net_freq = atol(buf);
354                                 break;
355                         case 29:
356                                 config.c_disable_newu = atoi(buf);
357                                 if (config.c_disable_newu != 0)
358                                         config.c_disable_newu = 1;
359                                 break;
360                         case 30:
361                                 /* niu */
362                                 break;
363                         case 31:
364                                 if ((config.c_purge_hour >= 0)
365                                    && (config.c_purge_hour <= 23)) {
366                                         config.c_purge_hour = atoi(buf);
367                                 }
368                                 break;
369 #ifdef HAVE_LDAP
370                         case 32:
371                                 safestrncpy(config.c_ldap_host, buf,
372                                             sizeof config.c_ldap_host);
373                                 break;
374                         case 33:
375                                 config.c_ldap_port = atoi(buf);
376                                 break;
377                         case 34:
378                                 safestrncpy(config.c_ldap_base_dn, buf,
379                                             sizeof config.c_ldap_base_dn);
380                                 break;
381                         case 35:
382                                 safestrncpy(config.c_ldap_bind_dn, buf,
383                                             sizeof config.c_ldap_bind_dn);
384                                 break;
385                         case 36:
386                                 safestrncpy(config.c_ldap_bind_pw, buf,
387                                             sizeof config.c_ldap_bind_pw);
388                                 break;
389 #endif
390                         case 37:
391                                 safestrncpy(config.c_ip_addr, buf,
392                                                 sizeof config.c_ip_addr);
393                         case 38:
394                                 config.c_msa_port = atoi(buf);
395                                 break;
396                         case 39:
397                                 config.c_imaps_port = atoi(buf);
398                                 break;
399                         case 40:
400                                 config.c_pop3s_port = atoi(buf);
401                                 break;
402                         case 41:
403                                 config.c_smtps_port = atoi(buf);
404                                 break;
405                         case 42:
406                                 config.c_enable_fulltext = atoi(buf);
407                                 break;
408                         case 43:
409                                 config.c_auto_cull = atoi(buf);
410                                 break;
411                         }
412                         ++a;
413                 }
414                 put_config();
415                 snprintf(buf, sizeof buf,
416                          "Global system configuration edited by %s\n",
417                          CC->curr_user);
418                 aide_message(buf);
419
420                 if (strlen(config.c_logpages) > 0)
421                         create_room(config.c_logpages, 3, "", 0, 1, 1, VIEW_BBS);
422
423                 /* If full text indexing has been disabled, invalidate the
424                  * index so it doesn't try to use it later.
425                  */
426                 if (!config.c_enable_fulltext == 0) {
427                         CitControl.fulltext_wordbreaker = 0;
428                         put_control();
429                 }
430         }
431
432         else if (!strcasecmp(cmd, "GETSYS")) {
433                 extract_token(confname, argbuf, 1, '|', sizeof confname);
434                 confptr = CtdlGetSysConfig(confname);
435                 if (confptr != NULL) {
436                         cprintf("%d %s\n", LISTING_FOLLOWS, confname);
437                         client_write(confptr, strlen(confptr));
438                         if (confptr[strlen(confptr) - 1] != 10)
439                                 client_write("\n", 1);
440                         cprintf("000\n");
441                         free(confptr);
442                 } else {
443                         cprintf("%d No such configuration.\n",
444                                 ERROR + ILLEGAL_VALUE);
445                 }
446         }
447
448         else if (!strcasecmp(cmd, "PUTSYS")) {
449                 extract_token(confname, argbuf, 1, '|', sizeof confname);
450                 unbuffer_output();
451                 cprintf("%d %s\n", SEND_LISTING, confname);
452                 confptr = CtdlReadMessageBody("000",
453                                 config.c_maxmsglen, NULL, 0);
454                 CtdlPutSysConfig(confname, confptr);
455                 free(confptr);
456         }
457
458         else {
459                 cprintf("%d Illegal option(s) specified.\n",
460                         ERROR + ILLEGAL_VALUE);
461         }
462 }