dca1e3d61985614f1071d60275514ecd3a278c27
[citadel.git] / citadel / utillib / citadel_dirs.c
1 /*
2  * citadel_dirs.c : calculate pathnames for various files used in the Citadel system
3  *
4  * Copyright (c) 1987-2018 by the citadel.org team
5  *
6  *  This program is open source software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License version 3.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  */
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <sys/stat.h>
17 #include <ctype.h>
18 #include <string.h>
19 #include <limits.h>
20 #include <time.h>
21 #include <errno.h>
22 #include <syslog.h>
23 #include <libcitadel.h>
24 #include "citadel.h"
25 #include "citadel_dirs.h"
26
27 /* our directories... */
28 char ctdl_home_directory[PATH_MAX] = "";
29 char ctdl_bio_dir[PATH_MAX]="bio";
30 char ctdl_data_dir[PATH_MAX]="data";
31 char ctdl_file_dir[PATH_MAX]="files";
32 char ctdl_shared_dir[PATH_MAX]="";
33 char ctdl_image_dir[PATH_MAX]="images";
34 char ctdl_info_dir[PATH_MAX]="info";
35 char ctdl_key_dir[PATH_MAX]=SSL_DIR;
36 char ctdl_message_dir[PATH_MAX]="messages";
37 char ctdl_usrpic_dir[PATH_MAX]="userpics";
38 char ctdl_bbsbase_dir[PATH_MAX]="";
39 char ctdl_etc_dir[PATH_MAX]="";
40 char ctdl_autoetc_dir[PATH_MAX]="";
41 /* attention! this may be non volatile on some oses */
42 char ctdl_run_dir[PATH_MAX]="";
43 char ctdl_spool_dir[PATH_MAX]="network";
44 char ctdl_netout_dir[PATH_MAX]="network/spoolout";
45 char ctdl_netdigest_dir[PATH_MAX]="network/digest";
46 char ctdl_nettmp_dir[PATH_MAX]="network/spooltmp";
47 char ctdl_netcfg_dir[PATH_MAX]="netconfigs";
48 char ctdl_utilbin_dir[PATH_MAX]="";
49 char ctdl_sbin_dir[PATH_MAX]="";
50 char ctdl_bin_dir[PATH_MAX]="";
51
52 /* some of our files, that are needed in several places */
53 char file_citadel_control[PATH_MAX]="";
54 char file_citadel_config[PATH_MAX]="";
55 char file_citadel_urlshorteners[PATH_MAX]="";
56 char file_lmtp_socket[PATH_MAX]="";
57 char file_lmtp_unfiltered_socket[PATH_MAX]="";
58 char file_arcq[PATH_MAX]="";
59 char file_citadel_socket[PATH_MAX]="";
60 char file_citadel_admin_socket[PATH_MAX]="";
61 char file_mail_aliases[PATH_MAX]="";
62 char file_pid_file[PATH_MAX]="";
63 char file_pid_paniclog[PATH_MAX]="";
64 char file_crpt_file_key[PATH_MAX]="";
65 char file_crpt_file_csr[PATH_MAX]="";
66 char file_crpt_file_cer[PATH_MAX]="";
67 char file_chkpwd[PATH_MAX]="";
68 char file_base64[PATH_MAX]="";
69 char file_guesstimezone[PATH_MAX]="";
70
71
72
73
74
75 #define COMPUTE_DIRECTORY(SUBDIR) memcpy(dirbuffer,SUBDIR, sizeof dirbuffer);\
76         snprintf(SUBDIR,sizeof SUBDIR,  "%s%s%s%s%s%s%s", \
77                          (home&!relh)?ctdl_home_directory:basedir, \
78              ((basedir!=ctdldir)&(home&!relh))?basedir:"/", \
79              ((basedir!=ctdldir)&(home&!relh))?"/":"", \
80                          relhome, \
81              (relhome[0]!='\0')?"/":"",\
82                          dirbuffer,\
83                          (dirbuffer[0]!='\0')?"/":"");
84
85 #define DBG_PRINT(A) if (dbg==1) fprintf (stderr,"%s : %s \n", #A, A)
86
87
88 void calc_dirs_n_files(int relh, int home, const char *relhome, char  *ctdldir, int dbg)
89 {
90         const char* basedir = "";
91         char dirbuffer[PATH_MAX] = "";
92
93         /*
94          * Ok, we keep our binaries either in the citadel base dir,
95          * or in /usr/sbin / /usr/bin
96          */
97         StripSlashes(ctdldir, 1);
98 #ifdef HAVE_ETC_DIR
99         snprintf(ctdl_sbin_dir, sizeof ctdl_sbin_dir, "/usr/sbin/");
100         snprintf(ctdl_bin_dir, sizeof ctdl_bin_dir, "/usr/bin/");
101 #else
102         snprintf(ctdl_sbin_dir, sizeof ctdl_sbin_dir, ctdldir);
103         snprintf(ctdl_bin_dir, sizeof ctdl_bin_dir, ctdldir);
104 #endif
105         StripSlashes(ctdl_sbin_dir, 1);
106         StripSlashes(ctdl_bin_dir, 1);
107
108 #ifndef HAVE_AUTO_ETC_DIR
109         basedir=ctdldir;
110 #else
111         basedir=AUTO_ETC_DIR;
112 #endif
113         COMPUTE_DIRECTORY(ctdl_autoetc_dir);
114         StripSlashes(ctdl_autoetc_dir, 1);
115
116 #ifndef HAVE_ETC_DIR
117         basedir=ctdldir;
118 #else
119         basedir=ETC_DIR;
120 #endif
121         COMPUTE_DIRECTORY(ctdl_netcfg_dir);
122         COMPUTE_DIRECTORY(ctdl_etc_dir);
123         StripSlashes(ctdl_netcfg_dir, 1);
124         StripSlashes(ctdl_etc_dir, 1);
125
126 #ifndef HAVE_UTILBIN_DIR
127         basedir=ctdldir;
128 #else
129         basedir=UTILBIN_DIR;
130 #endif
131         COMPUTE_DIRECTORY(ctdl_utilbin_dir);
132         StripSlashes(ctdl_utilbin_dir, 1);
133
134 #ifndef HAVE_RUN_DIR
135         basedir=ctdldir;
136 #else
137         basedir=RUN_DIR;
138 #endif
139         COMPUTE_DIRECTORY(ctdl_run_dir);
140         StripSlashes(ctdl_run_dir, 1);
141
142 #ifndef HAVE_STATICDATA_DIR
143         basedir=ctdldir;
144 #else
145         basedir=STATICDATA_DIR;
146 #endif
147         COMPUTE_DIRECTORY(ctdl_message_dir);
148         StripSlashes(ctdl_message_dir, 1);
149
150 #ifndef HAVE_DATA_DIR
151         basedir=ctdldir;
152 #else
153         basedir=DATA_DIR;
154 #endif
155         COMPUTE_DIRECTORY(ctdl_bio_dir);
156         COMPUTE_DIRECTORY(ctdl_data_dir);
157         COMPUTE_DIRECTORY(ctdl_file_dir);
158         COMPUTE_DIRECTORY(ctdl_image_dir);
159         COMPUTE_DIRECTORY(ctdl_info_dir);
160         COMPUTE_DIRECTORY(ctdl_usrpic_dir);
161         COMPUTE_DIRECTORY(ctdl_bbsbase_dir);
162
163         StripSlashes(ctdl_bio_dir, 1);
164         StripSlashes(ctdl_data_dir, 1);
165         StripSlashes(ctdl_file_dir, 1);
166         StripSlashes(ctdl_image_dir, 1);
167         StripSlashes(ctdl_info_dir, 1);
168         StripSlashes(ctdl_usrpic_dir, 1);
169         StripSlashes(ctdl_bbsbase_dir, 1);
170
171 #ifndef HAVE_SPOOL_DIR
172         basedir=ctdldir;
173 #else
174         basedir=SPOOL_DIR;
175 #endif
176         COMPUTE_DIRECTORY(ctdl_spool_dir);
177         COMPUTE_DIRECTORY(ctdl_netout_dir);
178         COMPUTE_DIRECTORY(ctdl_netdigest_dir);
179         COMPUTE_DIRECTORY(ctdl_nettmp_dir);
180
181         StripSlashes(ctdl_spool_dir, 1);
182         StripSlashes(ctdl_netout_dir, 1);
183         StripSlashes(ctdl_netdigest_dir, 1);
184         StripSlashes(ctdl_nettmp_dir, 1);
185
186         /* ok, now we know the dirs, calc some commonly used files */
187
188         snprintf(file_arcq, 
189                          sizeof file_arcq,
190                          "%srefcount_adjustments.dat",
191                          ctdl_autoetc_dir);
192         StripSlashes(file_arcq, 0);
193         snprintf(file_citadel_control, 
194                          sizeof file_citadel_control,
195                          "%scitadel.control",
196                          ctdl_autoetc_dir
197                          );
198         StripSlashes(file_citadel_control, 0);
199         snprintf(file_citadel_config, 
200                          sizeof file_citadel_config,
201                          "%scitadel.config",
202                          ctdl_autoetc_dir);
203         StripSlashes(file_citadel_config, 0);
204         snprintf(file_citadel_urlshorteners, 
205                          sizeof file_citadel_urlshorteners,
206                          "%scitadel_urlshorteners.rc",
207                          ctdl_etc_dir);
208         StripSlashes(file_citadel_urlshorteners, 0);
209         snprintf(file_lmtp_socket, 
210                          sizeof file_lmtp_socket,
211                          "%slmtp.socket",
212                          ctdl_run_dir);
213         StripSlashes(file_lmtp_socket, 0);
214         snprintf(file_lmtp_unfiltered_socket, 
215                          sizeof file_lmtp_socket,
216                          "%slmtp-unfiltered.socket",
217                          ctdl_run_dir);
218         StripSlashes(file_lmtp_unfiltered_socket, 0);
219         snprintf(file_citadel_socket, 
220                          sizeof file_citadel_socket,
221                                 "%scitadel.socket",
222                          ctdl_run_dir);
223         StripSlashes(file_citadel_socket, 0);
224         snprintf(file_citadel_admin_socket, 
225                          sizeof file_citadel_admin_socket,
226                                 "%scitadel-admin.socket",
227                          ctdl_run_dir);
228         StripSlashes(file_citadel_admin_socket, 0);
229         snprintf(file_pid_file, 
230                  sizeof file_pid_file,
231                  "%scitadel.pid",
232                  ctdl_run_dir);
233         StripSlashes(file_pid_file, 0);
234         snprintf(file_pid_paniclog, 
235                  sizeof file_pid_paniclog, 
236                  "%spanic.log",
237                  ctdl_home_directory);
238         StripSlashes(file_pid_paniclog, 0);
239         snprintf(file_crpt_file_key,
240                  sizeof file_crpt_file_key, 
241                  "%s/citadel.key",
242                  ctdl_key_dir);
243         StripSlashes(file_crpt_file_key, 0);
244         snprintf(file_crpt_file_csr,
245                  sizeof file_crpt_file_csr, 
246                  "%s/citadel.csr",
247                  ctdl_key_dir);
248         StripSlashes(file_crpt_file_csr, 0);
249         snprintf(file_crpt_file_cer,
250                  sizeof file_crpt_file_cer, 
251                  "%s/citadel.cer",
252                  ctdl_key_dir);
253         StripSlashes(file_crpt_file_cer, 0);
254         snprintf(file_chkpwd,
255                  sizeof file_chkpwd, 
256                  "%schkpwd",
257                  ctdl_utilbin_dir);
258         StripSlashes(file_chkpwd, 0);
259         snprintf(file_base64,
260                  sizeof file_base64,
261                  "%sbase64",
262                  ctdl_utilbin_dir);
263         StripSlashes(file_base64, 0);
264         snprintf(file_guesstimezone,
265                  sizeof file_guesstimezone,
266                  "%sguesstimezone.sh",
267                  ctdl_utilbin_dir);
268
269         /* 
270          * DIRTY HACK FOLLOWS! due to configs in the network dir in the 
271          * legacy installations, we need to calculate ifdeffed here.
272          */
273         snprintf(file_mail_aliases, 
274                  sizeof file_mail_aliases,
275                  "%smail.aliases",
276 #ifdef HAVE_ETC_DIR
277                  ctdl_etc_dir
278 #else
279                  ctdl_spool_dir
280 #endif
281                 );
282         StripSlashes(file_mail_aliases, 0);
283
284         DBG_PRINT(ctdl_bio_dir);
285         DBG_PRINT(ctdl_data_dir);
286         DBG_PRINT(ctdl_file_dir);
287         DBG_PRINT(ctdl_image_dir);
288         DBG_PRINT(ctdl_info_dir);
289         DBG_PRINT(ctdl_key_dir);
290         DBG_PRINT(ctdl_message_dir);
291         DBG_PRINT(ctdl_usrpic_dir);
292         DBG_PRINT(ctdl_etc_dir);
293         DBG_PRINT(ctdl_run_dir);
294         DBG_PRINT(ctdl_spool_dir);
295         DBG_PRINT(ctdl_netout_dir);
296         DBG_PRINT(ctdl_netdigest_dir);
297         DBG_PRINT(ctdl_nettmp_dir);
298         DBG_PRINT(ctdl_netcfg_dir);
299         DBG_PRINT(ctdl_bbsbase_dir);
300         DBG_PRINT(ctdl_sbin_dir);
301         DBG_PRINT(ctdl_bin_dir);
302         DBG_PRINT(ctdl_utilbin_dir);
303         DBG_PRINT(file_citadel_control);
304         DBG_PRINT(file_citadel_config);
305         DBG_PRINT(file_lmtp_socket);
306         DBG_PRINT(file_lmtp_unfiltered_socket);
307         DBG_PRINT(file_arcq);
308         DBG_PRINT(file_citadel_socket);
309         DBG_PRINT(file_mail_aliases);
310         DBG_PRINT(file_pid_file);
311         DBG_PRINT(file_pid_paniclog);
312         DBG_PRINT(file_crpt_file_key);
313         DBG_PRINT(file_crpt_file_csr);
314         DBG_PRINT(file_crpt_file_cer);
315         DBG_PRINT(file_chkpwd);
316         DBG_PRINT(file_base64);
317         DBG_PRINT(file_guesstimezone);
318 }
319
320
321 /*
322  * Generate an associated file name for a room
323  */
324 size_t assoc_file_name(char *buf, size_t n,
325                      struct ctdlroom *qrbuf, const char *prefix)
326 {
327         return snprintf(buf, n, "%s%ld", prefix, qrbuf->QRnumber);
328 }
329
330 void remove_digest_file(struct ctdlroom *room)
331 {
332         char buf[PATH_MAX];
333
334         snprintf(buf, PATH_MAX, "%s/%ld.eml", 
335                  ctdl_netdigest_dir,
336                  room->QRnumber);
337         StripSlashes(buf, 0);
338         unlink(buf);
339 }
340
341 FILE *create_digest_file(struct ctdlroom *room, int forceCreate)
342 {
343         struct stat stbuf;
344         char fn[PATH_MAX];
345         int exists;
346         FILE *fp;
347
348         snprintf(fn, PATH_MAX, "%s/%ld.eml", 
349                  ctdl_netdigest_dir,
350                  room->QRnumber);
351         StripSlashes(fn, 0);
352
353         exists = stat(fn, &stbuf); 
354         if (!forceCreate && (exists == -1))
355                 return NULL;
356         
357         fp = fopen(fn, "w+");
358         if (fp == NULL) {
359                 syslog(LOG_EMERG,
360                        "failed to create digest file %s: %s",
361                        fn,
362                        strerror(errno));
363         }
364         return fp;
365 }
366
367
368 int create_dir(char *which, long ACCESS, long UID, long GID)
369 {
370         int rv;
371         rv = mkdir(which, ACCESS);
372         if ((rv == -1) && (errno != EEXIST)) {
373                 syslog(LOG_EMERG,
374                        "failed to create directory %s: %s",
375                        which,
376                        strerror(errno));
377                 return rv;
378         }
379         rv = chmod(which, ACCESS);
380         if (rv == -1) {
381                 syslog(LOG_EMERG,
382                        "failed to set permissions for directory %s: %s",
383                        which,
384                        strerror(errno));
385                 return rv;
386         }
387         rv = chown(which, UID, GID);
388         if (rv == -1) {
389                 syslog(LOG_EMERG,
390                        "failed to set owner for directory %s: %s",
391                        which,
392                        strerror(errno));
393                 return rv;
394         }
395         return rv;
396 }
397
398 int create_run_directories(long UID, long GID)
399 {
400         int rv = 0;
401         rv += create_dir(ctdl_message_dir   , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
402         rv += create_dir(ctdl_file_dir      , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
403         rv += create_dir(ctdl_spool_dir     , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
404         rv += create_dir(ctdl_netout_dir    , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
405         rv += create_dir(ctdl_netdigest_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
406         rv += create_dir(ctdl_nettmp_dir    , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
407         rv += create_dir(ctdl_key_dir       , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1);
408         rv += create_dir(ctdl_run_dir       , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, UID, GID);
409         return rv;
410 }