Back to index

citadel  8.12
control.c
Go to the documentation of this file.
00001 /*
00002  * This module handles states which are global to the entire server.
00003  *
00004  * Copyright (c) 1987-2012 by the citadel.org team
00005  *
00006  *  This program is open source software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License version 3.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  */
00014 
00015 #include "sysdep.h"
00016 #include <stdlib.h>
00017 #include <unistd.h>
00018 #include <stdio.h>
00019 #include <fcntl.h>
00020 #include <signal.h>
00021 
00022 #if TIME_WITH_SYS_TIME
00023 # include <sys/time.h>
00024 # include <time.h>
00025 #else
00026 # if HAVE_SYS_TIME_H
00027 #  include <sys/time.h>
00028 # else
00029 #  include <time.h>
00030 # endif
00031 #endif
00032 
00033 #include <ctype.h>
00034 #include <string.h>
00035 #include <errno.h>
00036 #include <limits.h>
00037 #include <sys/types.h>
00038 #include <sys/file.h>
00039 #include <sys/stat.h>
00040 #include <libcitadel.h>
00041 #include "citadel.h"
00042 #include "server.h"
00043 #include "control.h"
00044 #include "sysdep_decls.h"
00045 #include "support.h"
00046 #include "config.h"
00047 #include "msgbase.h"
00048 #include "citserver.h"
00049 #include "room_ops.h"
00050 #include "user_ops.h"
00051 #include "database.h"
00052 #include "threads.h"
00053 
00054 #ifndef HAVE_SNPRINTF
00055 #include "snprintf.h"
00056 #endif
00057 
00058 #include "ctdl_module.h"
00059 
00060 struct CitControl CitControl;
00061 extern struct config config;
00062 FILE *control_fp = NULL;
00063 long control_highest_user = 0;
00064 
00065 
00066 /*
00067  * lock_control  -  acquire a lock on the control record file.
00068  *                  This keeps multiple citservers from running concurrently.
00069  */
00070 void lock_control(void)
00071 {
00072 #if defined(LOCK_EX) && defined(LOCK_NB)
00073        if (flock(fileno(control_fp), (LOCK_EX | LOCK_NB))) {
00074               syslog(LOG_EMERG, "citserver: unable to lock %s.\n", file_citadel_control);
00075               syslog(LOG_EMERG, "Is another citserver already running?\n");
00076               exit(CTDLEXIT_CONTROL);
00077        }
00078 #endif
00079 }
00080 
00081 /*
00082  * callback to get highest room number when rebuilding control file
00083  */
00084 void control_find_highest(struct ctdlroom *qrbuf, void *data)
00085 {
00086        struct ctdlroom room;
00087        struct cdbdata *cdbfr;
00088        long *msglist;
00089        int num_msgs=0;
00090        int c;
00091        int room_fixed = 0;
00092        int message_fixed = 0;
00093        
00094        if (qrbuf->QRnumber > CitControl.MMnextroom)
00095        {
00096               CitControl.MMnextroom = qrbuf->QRnumber;
00097               room_fixed = 1;
00098        }
00099               
00100        CtdlGetRoom (&room, qrbuf->QRname);
00101        
00102        /* Load the message list */
00103        cdbfr = cdb_fetch(CDB_MSGLISTS, &room.QRnumber, sizeof(long));
00104        if (cdbfr != NULL) {
00105               msglist = (long *) cdbfr->ptr;
00106               num_msgs = cdbfr->len / sizeof(long);
00107        } else {
00108               return;       /* No messages at all?  No further action. */
00109        }
00110 
00111        if (num_msgs>0)
00112        {
00113               for (c=0; c<num_msgs; c++)
00114               {
00115                      if (msglist[c] > CitControl.MMhighest)
00116                      {
00117                             CitControl.MMhighest = msglist[c];
00118                             message_fixed = 1;
00119                      }
00120               }
00121        }
00122        cdb_free(cdbfr);
00123        if (room_fixed)
00124               syslog(LOG_INFO, "Control record checking....Fixed room counter\n");
00125        if (message_fixed)
00126               syslog(LOG_INFO, "Control record checking....Fixed message count\n");
00127        return;
00128 }
00129 
00130 
00131 /*
00132  * Callback to get highest user number.
00133  */
00134  
00135 void control_find_user (struct ctdluser *EachUser, void *out_data)
00136 {
00137        int user_fixed = 0;
00138        
00139        if (EachUser->usernum > CitControl.MMnextuser)
00140        {
00141               CitControl.MMnextuser = EachUser->usernum;
00142               user_fixed = 1;
00143        }
00144        if(user_fixed)
00145               syslog(LOG_INFO, "Control record checking....Fixed user count\n");
00146 }
00147 
00148 
00149 /*
00150  * get_control  -  read the control record into memory.
00151  */
00152 void get_control(void)
00153 {
00154        static int already_have_control = 0;
00155        int rv = 0;
00156 
00157        /*
00158         * If we already have the control record in memory, there's no point
00159         * in reading it from disk again.
00160         */
00161        if (already_have_control) return;
00162 
00163        /* Zero it out.  If the control record on disk is missing or short,
00164         * the system functions with all control record fields initialized
00165         * to zero.
00166         */
00167        memset(&CitControl, 0, sizeof(struct CitControl));
00168        if (control_fp == NULL) {
00169               control_fp = fopen(file_citadel_control, "rb+");
00170               if (control_fp != NULL) {
00171                      lock_control();
00172                      rv = fchown(fileno(control_fp), config.c_ctdluid, -1);
00173                      if (rv == -1)
00174                             syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]\n", 
00175                                    file_citadel_control, strerror(errno));
00176                      rv = fchmod(fileno(control_fp), S_IRUSR|S_IWUSR);
00177                      if (rv == -1)
00178                             syslog(LOG_EMERG, "Failed to adjust accessrights of: %s [%s]\n", 
00179                                    file_citadel_control, strerror(errno));
00180               }
00181        }
00182        if (control_fp == NULL) {
00183               control_fp = fopen(file_citadel_control, "wb+");
00184               if (control_fp != NULL) {
00185                      lock_control();
00186                      memset(&CitControl, 0, sizeof(struct CitControl));
00187 
00188                      rv = fchown(fileno(control_fp), config.c_ctdluid, -1);
00189                      if (rv == -1)
00190                             syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]\n", 
00191                                    file_citadel_control, strerror(errno));
00192 
00193                      rv = fchmod(fileno(control_fp), S_IRUSR|S_IWUSR);
00194                      if (rv == -1)
00195                             syslog(LOG_EMERG, "Failed to adjust accessrights of: %s [%s]\n", 
00196                                    file_citadel_control, strerror(errno));
00197                      rv = fwrite(&CitControl, sizeof(struct CitControl), 1, control_fp);
00198                      if (rv == -1)
00199                             syslog(LOG_EMERG, "Failed to write: %s [%s]\n", 
00200                                    file_citadel_control, strerror(errno));
00201                      rewind(control_fp);
00202               }
00203        }
00204        if (control_fp == NULL) {
00205               syslog(LOG_ALERT, "ERROR opening %s: %s\n", file_citadel_control, strerror(errno));
00206               return;
00207        }
00208 
00209        rewind(control_fp);
00210        rv = fread(&CitControl, sizeof(struct CitControl), 1, control_fp);
00211        if (rv == -1)
00212               syslog(LOG_EMERG, "Failed to read Controlfile: %s [%s]\n", 
00213                      file_citadel_control, strerror(errno));
00214        already_have_control = 1;
00215        rv = chown(file_citadel_control, config.c_ctdluid, (-1));
00216        if (rv == -1)
00217               syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]\n", 
00218                      file_citadel_control, strerror(errno));   
00219 }
00220 
00221 /*
00222  * put_control  -  write the control record to disk.
00223  */
00224 void put_control(void)
00225 {
00226        int rv = 0;
00227 
00228        if (control_fp != NULL) {
00229               rewind(control_fp);
00230               rv = fwrite(&CitControl, sizeof(struct CitControl), 1, control_fp);
00231               if (rv == -1)
00232                      syslog(LOG_EMERG, "Failed to write: %s [%s]\n", 
00233                             file_citadel_control, strerror(errno));
00234               fflush(control_fp);
00235        }
00236 }
00237 
00238 
00239 /*
00240  * check_control   -  check the control record has sensible values for message, user and room numbers
00241  */
00242 void check_control(void)
00243 {
00244        syslog(LOG_INFO, "Checking/re-building control record\n");
00245        get_control();
00246        // Find highest room number and message number.
00247        CtdlForEachRoom(control_find_highest, NULL);
00248        ForEachUser(control_find_user, NULL);
00249        put_control();
00250 }
00251 
00252 
00253 /*
00254  * release_control - close our fd on exit
00255  */
00256 void release_control(void)
00257 {
00258        if (control_fp != NULL) {
00259               fclose(control_fp);
00260        }
00261        control_fp = NULL;
00262 }
00263 
00264 /*
00265  * get_new_message_number()  -  Obtain a new, unique ID to be used for a message.
00266  */
00267 long get_new_message_number(void)
00268 {
00269        long retval = 0L;
00270        begin_critical_section(S_CONTROL);
00271        get_control();
00272        retval = ++CitControl.MMhighest;
00273        put_control();
00274        end_critical_section(S_CONTROL);
00275        return(retval);
00276 }
00277 
00278 
00279 /*
00280  * CtdlGetCurrentMessageNumber()  -  Obtain the current highest message number in the system
00281  * This provides a quick way to initialise a variable that might be used to indicate
00282  * messages that should not be processed. EG. a new Sieve script will use this
00283  * to record determine that messages older than this should not be processed.
00284  */
00285 long CtdlGetCurrentMessageNumber(void)
00286 {
00287        long retval = 0L;
00288        begin_critical_section(S_CONTROL);
00289        get_control();
00290        retval = CitControl.MMhighest;
00291        end_critical_section(S_CONTROL);
00292        return(retval);
00293 }
00294 
00295 
00296 /*
00297  * get_new_user_number()  -  Obtain a new, unique ID to be used for a user.
00298  */
00299 long get_new_user_number(void)
00300 {
00301        long retval = 0L;
00302        begin_critical_section(S_CONTROL);
00303        get_control();
00304        retval = ++CitControl.MMnextuser;
00305        put_control();
00306        end_critical_section(S_CONTROL);
00307        return(retval);
00308 }
00309 
00310 
00311 
00312 /*
00313  * get_new_room_number()  -  Obtain a new, unique ID to be used for a room.
00314  */
00315 long get_new_room_number(void)
00316 {
00317        long retval = 0L;
00318        begin_critical_section(S_CONTROL);
00319        get_control();
00320        retval = ++CitControl.MMnextroom;
00321        put_control();
00322        end_critical_section(S_CONTROL);
00323        return(retval);
00324 }
00325 
00326 
00327 
00328 /* 
00329  * Get or set global configuration options
00330  *
00331  * IF YOU ADD OR CHANGE FIELDS HERE, YOU *MUST* DOCUMENT YOUR CHANGES AT:
00332  * http://www.citadel.org/doku.php?id=documentation:applicationprotocol
00333  *
00334  */
00335 void cmd_conf(char *argbuf)
00336 {
00337        char cmd[16];
00338        char buf[256];
00339        int a;
00340        char *confptr;
00341        char confname[128];
00342 
00343        if (CtdlAccessCheck(ac_aide)) return;
00344 
00345        extract_token(cmd, argbuf, 0, '|', sizeof cmd);
00346        if (!strcasecmp(cmd, "GET")) {
00347               cprintf("%d Configuration...\n", LISTING_FOLLOWS);
00348               cprintf("%s\n", config.c_nodename);
00349               cprintf("%s\n", config.c_fqdn);
00350               cprintf("%s\n", config.c_humannode);
00351               cprintf("%s\n", config.c_phonenum);
00352               cprintf("%d\n", config.c_creataide);
00353               cprintf("%d\n", config.c_sleeping);
00354               cprintf("%d\n", config.c_initax);
00355               cprintf("%d\n", config.c_regiscall);
00356               cprintf("%d\n", config.c_twitdetect);
00357               cprintf("%s\n", config.c_twitroom);
00358               cprintf("%s\n", config.c_moreprompt);
00359               cprintf("%d\n", config.c_restrict);
00360               cprintf("%s\n", config.c_site_location);
00361               cprintf("%s\n", config.c_sysadm);
00362               cprintf("%d\n", config.c_maxsessions);
00363               cprintf("xxx\n"); /* placeholder -- field no longer in use */
00364               cprintf("%d\n", config.c_userpurge);
00365               cprintf("%d\n", config.c_roompurge);
00366               cprintf("%s\n", config.c_logpages);
00367               cprintf("%d\n", config.c_createax);
00368               cprintf("%ld\n", config.c_maxmsglen);
00369               cprintf("%d\n", config.c_min_workers);
00370               cprintf("%d\n", config.c_max_workers);
00371               cprintf("%d\n", config.c_pop3_port);
00372               cprintf("%d\n", config.c_smtp_port);
00373               cprintf("%d\n", config.c_rfc822_strict_from);
00374               cprintf("%d\n", config.c_aide_zap);
00375               cprintf("%d\n", config.c_imap_port);
00376               cprintf("%ld\n", config.c_net_freq);
00377               cprintf("%d\n", config.c_disable_newu);
00378               cprintf("1\n");      /* niu */
00379               cprintf("%d\n", config.c_purge_hour);
00380 #ifdef HAVE_LDAP
00381               cprintf("%s\n", config.c_ldap_host);
00382               cprintf("%d\n", config.c_ldap_port);
00383               cprintf("%s\n", config.c_ldap_base_dn);
00384               cprintf("%s\n", config.c_ldap_bind_dn);
00385               cprintf("%s\n", config.c_ldap_bind_pw);
00386 #else
00387               cprintf("\n");
00388               cprintf("0\n");
00389               cprintf("\n");
00390               cprintf("\n");
00391               cprintf("\n");
00392 #endif
00393               cprintf("%s\n", config.c_ip_addr);
00394               cprintf("%d\n", config.c_msa_port);
00395               cprintf("%d\n", config.c_imaps_port);
00396               cprintf("%d\n", config.c_pop3s_port);
00397               cprintf("%d\n", config.c_smtps_port);
00398               cprintf("%d\n", config.c_enable_fulltext);
00399               cprintf("%d\n", config.c_auto_cull);
00400               cprintf("%d\n", config.c_instant_expunge);
00401               cprintf("%d\n", config.c_allow_spoofing);
00402               cprintf("%d\n", config.c_journal_email);
00403               cprintf("%d\n", config.c_journal_pubmsgs);
00404               cprintf("%s\n", config.c_journal_dest);
00405               cprintf("%s\n", config.c_default_cal_zone);
00406               cprintf("%d\n", config.c_pftcpdict_port);
00407               cprintf("%d\n", config.c_managesieve_port);
00408                cprintf("%d\n", config.c_auth_mode);
00409                cprintf("%s\n", config.c_funambol_host);
00410                cprintf("%d\n", config.c_funambol_port);
00411                cprintf("%s\n", config.c_funambol_source);
00412                cprintf("%s\n", config.c_funambol_auth);
00413               cprintf("%d\n", config.c_rbl_at_greeting);
00414               cprintf("%s\n", config.c_master_user);
00415               cprintf("%s\n", config.c_master_pass);
00416               cprintf("%s\n", config.c_pager_program);
00417               cprintf("%d\n", config.c_imap_keep_from);
00418               cprintf("%d\n", config.c_xmpp_c2s_port);
00419               cprintf("%d\n", config.c_xmpp_s2s_port);
00420               cprintf("%ld\n", config.c_pop3_fetch);
00421               cprintf("%ld\n", config.c_pop3_fastest);
00422               cprintf("%d\n", config.c_spam_flag_only);
00423               cprintf("%d\n", config.c_guest_logins);
00424               cprintf("%d\n", config.c_port_number);
00425               cprintf("%d\n", config.c_ctdluid);
00426               cprintf("000\n");
00427        }
00428 
00429        else if (!strcasecmp(cmd, "SET")) {
00430               unbuffer_output();
00431               cprintf("%d Send configuration...\n", SEND_LISTING);
00432               a = 0;
00433               while (client_getln(buf, sizeof buf) >= 0 && strcmp(buf, "000")) {
00434                      switch (a) {
00435                      case 0:
00436                             safestrncpy(config.c_nodename, buf,
00437                                        sizeof config.c_nodename);
00438                             break;
00439                      case 1:
00440                             safestrncpy(config.c_fqdn, buf,
00441                                        sizeof config.c_fqdn);
00442                             break;
00443                      case 2:
00444                             safestrncpy(config.c_humannode, buf,
00445                                        sizeof config.c_humannode);
00446                             break;
00447                      case 3:
00448                             safestrncpy(config.c_phonenum, buf,
00449                                        sizeof config.c_phonenum);
00450                             break;
00451                      case 4:
00452                             config.c_creataide = atoi(buf);
00453                             break;
00454                      case 5:
00455                             config.c_sleeping = atoi(buf);
00456                             break;
00457                      case 6:
00458                             config.c_initax = atoi(buf);
00459                             if (config.c_initax < 1)
00460                                    config.c_initax = 1;
00461                             if (config.c_initax > 6)
00462                                    config.c_initax = 6;
00463                             break;
00464                      case 7:
00465                             config.c_regiscall = atoi(buf);
00466                             if (config.c_regiscall != 0)
00467                                    config.c_regiscall = 1;
00468                             break;
00469                      case 8:
00470                             config.c_twitdetect = atoi(buf);
00471                             if (config.c_twitdetect != 0)
00472                                    config.c_twitdetect = 1;
00473                             break;
00474                      case 9:
00475                             safestrncpy(config.c_twitroom, buf,
00476                                        sizeof config.c_twitroom);
00477                             break;
00478                      case 10:
00479                             safestrncpy(config.c_moreprompt, buf,
00480                                        sizeof config.c_moreprompt);
00481                             break;
00482                      case 11:
00483                             config.c_restrict = atoi(buf);
00484                             if (config.c_restrict != 0)
00485                                    config.c_restrict = 1;
00486                             break;
00487                      case 12:
00488                             safestrncpy(config.c_site_location, buf,
00489                                        sizeof config.c_site_location);
00490                             break;
00491                      case 13:
00492                             safestrncpy(config.c_sysadm, buf,
00493                                        sizeof config.c_sysadm);
00494                             break;
00495                      case 14:
00496                             config.c_maxsessions = atoi(buf);
00497                             if (config.c_maxsessions < 0)
00498                                    config.c_maxsessions = 0;
00499                             break;
00500                      case 15:
00501                             /* placeholder -- field no longer in use */
00502                             break;
00503                      case 16:
00504                             config.c_userpurge = atoi(buf);
00505                             break;
00506                      case 17:
00507                             config.c_roompurge = atoi(buf);
00508                             break;
00509                      case 18:
00510                             safestrncpy(config.c_logpages, buf,
00511                                        sizeof config.c_logpages);
00512                             break;
00513                      case 19:
00514                             config.c_createax = atoi(buf);
00515                             if (config.c_createax < 1)
00516                                    config.c_createax = 1;
00517                             if (config.c_createax > 6)
00518                                    config.c_createax = 6;
00519                             break;
00520                      case 20:
00521                             if (atoi(buf) >= 8192)
00522                                    config.c_maxmsglen = atoi(buf);
00523                             break;
00524                      case 21:
00525                             if (atoi(buf) >= 2)
00526                                    config.c_min_workers = atoi(buf);
00527                      case 22:
00528                             if (atoi(buf) >= config.c_min_workers)
00529                                    config.c_max_workers = atoi(buf);
00530                      case 23:
00531                             config.c_pop3_port = atoi(buf);
00532                             break;
00533                      case 24:
00534                             config.c_smtp_port = atoi(buf);
00535                             break;
00536                      case 25:
00537                             config.c_rfc822_strict_from = atoi(buf);
00538                             break;
00539                      case 26:
00540                             config.c_aide_zap = atoi(buf);
00541                             if (config.c_aide_zap != 0)
00542                                    config.c_aide_zap = 1;
00543                             break;
00544                      case 27:
00545                             config.c_imap_port = atoi(buf);
00546                             break;
00547                      case 28:
00548                             config.c_net_freq = atol(buf);
00549                             break;
00550                      case 29:
00551                             config.c_disable_newu = atoi(buf);
00552                             if (config.c_disable_newu != 0)
00553                                    config.c_disable_newu = 1;
00554                             break;
00555                      case 30:
00556                             /* niu */
00557                             break;
00558                      case 31:
00559                             if ((config.c_purge_hour >= 0)
00560                                && (config.c_purge_hour <= 23)) {
00561                                    config.c_purge_hour = atoi(buf);
00562                             }
00563                             break;
00564 #ifdef HAVE_LDAP
00565                      case 32:
00566                             safestrncpy(config.c_ldap_host, buf,
00567                                        sizeof config.c_ldap_host);
00568                             break;
00569                      case 33:
00570                             config.c_ldap_port = atoi(buf);
00571                             break;
00572                      case 34:
00573                             safestrncpy(config.c_ldap_base_dn, buf,
00574                                        sizeof config.c_ldap_base_dn);
00575                             break;
00576                      case 35:
00577                             safestrncpy(config.c_ldap_bind_dn, buf,
00578                                        sizeof config.c_ldap_bind_dn);
00579                             break;
00580                      case 36:
00581                             safestrncpy(config.c_ldap_bind_pw, buf,
00582                                        sizeof config.c_ldap_bind_pw);
00583                             break;
00584 #endif
00585                      case 37:
00586                             safestrncpy(config.c_ip_addr, buf,
00587                                           sizeof config.c_ip_addr);
00588                      case 38:
00589                             config.c_msa_port = atoi(buf);
00590                             break;
00591                      case 39:
00592                             config.c_imaps_port = atoi(buf);
00593                             break;
00594                      case 40:
00595                             config.c_pop3s_port = atoi(buf);
00596                             break;
00597                      case 41:
00598                             config.c_smtps_port = atoi(buf);
00599                             break;
00600                      case 42:
00601                             config.c_enable_fulltext = atoi(buf);
00602                             break;
00603                      case 43:
00604                             config.c_auto_cull = atoi(buf);
00605                             break;
00606                      case 44:
00607                             config.c_instant_expunge = atoi(buf);
00608                             break;
00609                      case 45:
00610                             config.c_allow_spoofing = atoi(buf);
00611                             break;
00612                      case 46:
00613                             config.c_journal_email = atoi(buf);
00614                             break;
00615                      case 47:
00616                             config.c_journal_pubmsgs = atoi(buf);
00617                             break;
00618                      case 48:
00619                             safestrncpy(config.c_journal_dest, buf,
00620                                           sizeof config.c_journal_dest);
00621                      case 49:
00622                             safestrncpy(config.c_default_cal_zone, buf,
00623                                           sizeof config.c_default_cal_zone);
00624                             break;
00625                      case 50:
00626                             config.c_pftcpdict_port = atoi(buf);
00627                             break;
00628                      case 51:
00629                             config.c_managesieve_port = atoi(buf);
00630                             break;
00631                      case 52:
00632                             config.c_auth_mode = atoi(buf);
00633                      case 53:
00634                             safestrncpy(config.c_funambol_host, buf,
00635                                    sizeof config.c_funambol_host);
00636                             break;
00637                      case 54:
00638                             config.c_funambol_port = atoi(buf);
00639                             break;
00640                      case 55:
00641                             safestrncpy(config.c_funambol_source,
00642                                    buf, 
00643                                    sizeof config.c_funambol_source);
00644                             break;
00645                      case 56:
00646                             safestrncpy(config.c_funambol_auth,
00647                                    buf,
00648                                    sizeof config.c_funambol_auth);
00649                             break;
00650                      case 57:
00651                             config.c_rbl_at_greeting = atoi(buf);
00652                             break;
00653                      case 58:
00654                             safestrncpy(config.c_master_user, buf, sizeof config.c_master_user);
00655                             break;
00656                      case 59:
00657                             safestrncpy(config.c_master_pass, buf, sizeof config.c_master_pass);
00658                             break;
00659                      case 60:
00660                             safestrncpy(config.c_pager_program,
00661                                    buf,
00662                                    sizeof config.c_pager_program);
00663                             break;
00664                      case 61:
00665                             config.c_imap_keep_from = atoi(buf);
00666                             break;
00667                      case 62:
00668                             config.c_xmpp_c2s_port = atoi(buf);
00669                             break;
00670                      case 63:
00671                             config.c_xmpp_s2s_port = atoi(buf);
00672                             break;
00673                      case 64:
00674                             config.c_pop3_fetch = atol(buf);
00675                             break;
00676                      case 65:
00677                             config.c_pop3_fastest = atol(buf);
00678                             break;
00679                      case 66:
00680                             config.c_spam_flag_only = atoi(buf);
00681                             break;
00682                      case 67:
00683                             config.c_guest_logins = atoi(buf);
00684                             break;
00685                      case 68:
00686                             config.c_port_number = atoi(buf);
00687                             break;
00688                      case 69:
00689                             config.c_ctdluid = atoi(buf);
00690                             break;
00691                      }
00692                      ++a;
00693               }
00694               put_config();
00695               snprintf(buf, sizeof buf,
00696                      "The global system configuration has been edited by %s.\n",
00697                       (CC->logged_in ? CC->curr_user : "an administrator")
00698               );
00699               CtdlAideMessage(buf,"Citadel Configuration Manager Message");
00700 
00701               if (!IsEmptyStr(config.c_logpages))
00702                      CtdlCreateRoom(config.c_logpages, 3, "", 0, 1, 1, VIEW_BBS);
00703 
00704               /* If full text indexing has been disabled, invalidate the
00705                * index so it doesn't try to use it later.
00706                */
00707               if (config.c_enable_fulltext == 0) {
00708                      CitControl.fulltext_wordbreaker = 0;
00709                      put_control();
00710               }
00711        }
00712 
00713        else if (!strcasecmp(cmd, "GETSYS")) {
00714               extract_token(confname, argbuf, 1, '|', sizeof confname);
00715               confptr = CtdlGetSysConfig(confname);
00716               if (confptr != NULL) {
00717                      long len; 
00718 
00719                      len = strlen(confptr);
00720                      cprintf("%d %s\n", LISTING_FOLLOWS, confname);
00721                      client_write(confptr, len);
00722                      if ((len > 0) && (confptr[len - 1] != 10))
00723                             client_write("\n", 1);
00724                      cprintf("000\n");
00725                      free(confptr);
00726               } else {
00727                      cprintf("%d No such configuration.\n",
00728                             ERROR + ILLEGAL_VALUE);
00729               }
00730        }
00731 
00732        else if (!strcasecmp(cmd, "PUTSYS")) {
00733               extract_token(confname, argbuf, 1, '|', sizeof confname);
00734               unbuffer_output();
00735               cprintf("%d %s\n", SEND_LISTING, confname);
00736               confptr = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
00737               CtdlPutSysConfig(confname, confptr);
00738               free(confptr);
00739        }
00740 
00741        else {
00742               cprintf("%d Illegal option(s) specified.\n",
00743                      ERROR + ILLEGAL_VALUE);
00744        }
00745 }
00746 
00747 
00748 /*****************************************************************************/
00749 /*                      MODULE INITIALIZATION STUFF                          */
00750 /*****************************************************************************/
00751 
00752 
00753 CTDL_MODULE_INIT(control)
00754 {
00755        if (!threading) {
00756               CtdlRegisterProtoHook(cmd_conf, "CONF", "get/set system configuration");
00757        }
00758        /* return our id for the Log */
00759        return "control";
00760 }