Fix warnings all over citserver; handle function replies; remove unused code.
[citadel.git] / citadel / config.c
1 /*
2  * Read and write the citadel.config file
3  *
4  * Copyright (c) 1987-2009 by the citadel.org team
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "sysdep.h"
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <limits.h>
29 #include <libcitadel.h>
30 #include "citadel.h"
31 #include "server.h"
32 #include "config.h"
33
34
35 #include "ctdl_module.h"
36
37
38 struct config config;
39
40 /*
41  * get_config() is called during the initialization of any program which
42  * directly accesses Citadel data files.  It verifies the system's integrity
43  * and reads citadel.config into memory.
44  */
45 void get_config(void) {
46         FILE *cfp;
47         struct stat st;
48         int rv;
49
50         if (chdir(ctdl_bbsbase_dir) != 0) {
51                 fprintf(stderr,
52                         "This program could not be started.\n"
53                         "Unable to change directory to %s\n"
54                         "Error: %s\n",
55                         ctdl_bbsbase_dir,
56                         strerror(errno));
57                 exit(CTDLEXIT_HOME);
58         }
59         cfp = fopen(file_citadel_config, "rb");
60         if (cfp == NULL) {
61                 fprintf(stderr, "This program could not be started.\n"
62                                 "Unable to open %s\n"
63                                 "Error: %s\n",
64                                 file_citadel_config,
65                                 strerror(errno));
66                 exit(CTDLEXIT_CONFIG);
67         }
68         memset(&config, 0, sizeof(struct config));
69         rv = fread((char *) &config, sizeof(struct config), 1, cfp);
70         if (rv != 1)
71         {
72                 fprintf(stderr, 
73                         "Warning: The config file %s has unexpected size. \n",
74                         file_citadel_config);
75         }
76         if (fstat(fileno(cfp), &st)) {
77                 perror(file_citadel_config);
78                 exit(CTDLEXIT_CONFIG);
79         }
80
81 #ifndef __CYGWIN__
82         if (st.st_uid != CTDLUID) {
83                 fprintf(stderr, "%s must be owned by uid="F_UID_T" but "F_UID_T" owns it!\n", 
84                         file_citadel_config, CTDLUID, st.st_uid);
85                 exit(CTDLEXIT_CONFIG);
86         }
87         int desired_mode = (S_IFREG | S_IRUSR | S_IWUSR) ;
88         if (st.st_mode != desired_mode) {
89                 fprintf(stderr, "%s must be set to permissions mode %03o but they are %03o\n",
90                         file_citadel_config, (desired_mode & 0xFFF), (st.st_mode & 0xFFF));
91                 exit(CTDLEXIT_CONFIG);
92         }
93 #endif
94
95         fclose(cfp);
96
97         /* Ensure that we are linked to the correct version of libcitadel */
98         if (libcitadel_version_number() < LIBCITADEL_VERSION_NUMBER) {
99                 fprintf(stderr, "    You are running libcitadel version %d.%02d\n",
100                         (libcitadel_version_number() / 100), (libcitadel_version_number() % 100));
101                 fprintf(stderr, "citserver was compiled against version %d.%02d\n",
102                         (LIBCITADEL_VERSION_NUMBER / 100), (LIBCITADEL_VERSION_NUMBER % 100));
103                 exit(CTDLEXIT_LIBCITADEL);
104         }
105
106         /* Only allow LDAP auth mode if we actually have LDAP support */
107 #ifndef HAVE_LDAP
108         if ((config.c_auth_mode == AUTHMODE_LDAP) || (config.c_auth_mode == AUTHMODE_LDAP_AD)) {
109                 fprintf(stderr, "Your system is configured for LDAP authentication,\n"
110                                 "but you are running a server built without OpenLDAP support.\n");
111                 exit(CTDL_EXIT_UNSUP_AUTH);
112         }
113 #endif
114
115         /* Check to see whether 'setup' must first be run to update data file formats */
116         if (config.c_setup_level < REV_MIN) {
117                 fprintf(stderr, "Your data files are out of date.  Run setup to update them.\n");
118                 fprintf(stderr, "        This program requires level %d.%02d\n",
119                         (REV_LEVEL / 100), (REV_LEVEL % 100));
120                 fprintf(stderr, "        Data files are currently at %d.%02d\n",
121                         (config.c_setup_level / 100),
122                         (config.c_setup_level % 100));
123                 exit(CTDLEXIT_OOD);
124         }
125
126         /* Default maximum message length is 10 megabytes.  This is site
127          * configurable.  Also check to make sure the limit has not been
128          * set below 8192 bytes.
129          */
130         if (config.c_maxmsglen <= 0)
131                 config.c_maxmsglen = 10485760;
132         if (config.c_maxmsglen < 8192)
133                 config.c_maxmsglen = 8192;
134
135         /* Default lower and upper limits on number of worker threads */
136
137         if (config.c_min_workers < 3)           /* no less than 3 */
138                 config.c_min_workers = 5;
139
140         if (config.c_max_workers == 0)                  /* default maximum */
141                 config.c_max_workers = 256;
142
143         if (config.c_max_workers < config.c_min_workers)   /* max >= min */
144                 config.c_max_workers = config.c_min_workers;
145
146         /* Networking more than once every five minutes just isn't sane */
147         if (config.c_net_freq == 0L)
148                 config.c_net_freq = 3600L;      /* once per hour default */
149         if (config.c_net_freq < 300L) 
150                 config.c_net_freq = 300L;
151
152         /* Same goes for POP3 */
153         if (config.c_pop3_fetch == 0L)
154                 config.c_pop3_fetch = 3600L;    /* once per hour default */
155         if (config.c_pop3_fetch < 300L) 
156                 config.c_pop3_fetch = 300L;
157         if (config.c_pop3_fastest == 0L)
158                 config.c_pop3_fastest = 3600L;  /* once per hour default */
159         if (config.c_pop3_fastest < 300L) 
160                 config.c_pop3_fastest = 300L;
161
162         /* "create new user" only works with native authentication mode */
163         if (config.c_auth_mode != AUTHMODE_NATIVE) {
164                 config.c_disable_newu = 1;
165         }
166 }
167
168
169 /*
170  * Occasionally, we will need to write the config file, because some operations
171  * change site-wide parameters.
172  */
173 void put_config(void)
174 {
175         FILE *cfp;
176         int rv;
177
178         if ((cfp = fopen(file_citadel_config, "rb+")) == NULL)
179                 perror(file_citadel_config);
180         else {
181                 rv = fwrite((char *) &config, sizeof(struct config), 1, cfp);
182                 if (rv == -1)
183                         syslog(LOG_EMERG, "Failed to write: %s [%s]\n", 
184                                file_citadel_config, strerror(errno));
185                 fclose(cfp);
186         }
187 }