/[pkg-mixmaster]/trunk/Mix/Src/mix.c
ViewVC logotype

Contents of /trunk/Mix/Src/mix.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 177 - (show annotations) (download)
Sun Aug 25 07:47:23 2002 UTC (10 years, 8 months ago) by weaselp
File MIME type: text/plain
File size: 26509 byte(s)
Mixmaster in daemon mode will now reload its configuration upon receiving a
SIGHUP.

It was necessary to set the defaults in their own function rather than when
defining the variables.

It will also catch SIGTERM and SIGINT and exit in a sane way, first finishing
the current action.

New option --no-detach will prevent mixmaster in daemon mode from detaching
from the terminal.
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Mixmaster initialization, configuration
9 $Id: mix.c,v 1.16 2002/08/25 07:47:23 weaselp Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdarg.h>
17 #include <ctype.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #ifdef POSIX
22 #include <signal.h>
23 #include <unistd.h>
24 #include <pwd.h>
25 #include <sys/utsname.h>
26 #else
27 #include <io.h>
28 #include <direct.h>
29 #endif
30 #ifdef WIN32
31 #include <windows.h>
32 #endif
33 #include <assert.h>
34 #include "menu.h"
35
36 int buf_vappendf(BUFFER *b, char *fmt, va_list args);
37
38 /** filenames ************************************************************/
39 char MIXCONF[PATHMAX];
40 char DISCLAIMFILE[PATHMAX];
41 char FROMDSCLFILE[PATHMAX];
42 char MSGFOOTERFILE[PATHMAX];
43 char POP3CONF[PATHMAX];
44 char HELPFILE[PATHMAX];
45 char ABUSEFILE[PATHMAX];
46 char REPLYFILE[PATHMAX];
47 char USAGEFILE[PATHMAX];
48 char USAGELOG[PATHMAX];
49 char BLOCKFILE[PATHMAX];
50 char ADMKEYFILE[PATHMAX];
51 char KEYFILE[PATHMAX];
52 char PGPKEY[PATHMAX];
53 char DSAPARAMS[PATHMAX];
54 char DHPARAMS[PATHMAX];
55 char MIXRAND[PATHMAX];
56 char SECRING[PATHMAX];
57 char PUBRING[PATHMAX];
58 char IDLOG[PATHMAX];
59 char STATS[PATHMAX];
60 char DESTBLOCK[PATHMAX];
61 char DESTALLOW[PATHMAX];
62 char SOURCEBLOCK[PATHMAX];
63 char HDRFILTER[PATHMAX];
64 char REGULAR[PATHMAX];
65 char POOL[PATHMAX];
66 char TYPE1LIST[PATHMAX];
67 char TYPE2REL[PATHMAX];
68 char TYPE2LIST[PATHMAX];
69
70 char PGPREMPUBRING[PATHMAX];
71 char PGPREMPUBASC[PATHMAX];
72 char PGPREMSECRING[PATHMAX];
73 char NYMSECRING[PATHMAX];
74 char NYMDB[PATHMAX];
75
76
77 /** config ***************************************************************/
78
79 char MIXDIR[PATHMAX];
80 char POOLDIR[PATHMAX];
81
82 /* programs */
83 char SENDMAIL[LINELEN];
84 char SENDANONMAIL[LINELEN];
85 char NEWS[LINELEN];
86 char TYPE1[LINELEN];
87
88 /* addresses */
89 char MAILtoNEWS[LINELEN];
90 char REMAILERNAME[LINELEN];
91 char ANONNAME[LINELEN];
92 char REMAILERADDR[LINELEN];
93 char ANONADDR[LINELEN];
94 char COMPLAINTS[LINELEN];
95 int AUTOREPLY;
96 char SMTPRELAY[LINELEN];
97
98 #ifdef USE_SOCK
99 char HELONAME[LINELEN];
100 char ENVFROM[LINELEN];
101 int POP3DEL;
102 int POP3SIZELIMIT;
103 long POP3TIME;
104
105 #endif
106
107 char SHORTNAME[LINELEN];
108
109 /* remailer configuration */
110 int REMAIL;
111 int MIX;
112 int PGP;
113 int UNENCRYPTED;
114 int REMIX;
115 int REPGP;
116
117 int POOLSIZE;
118 int RATE;
119 int MIDDLEMAN;
120 int AUTOBLOCK;
121 char FORWARDTO[LINELEN];
122 int SIZELIMIT; /* maximal size of remailed messages */
123 int INFLATEMAX; /* maximal size of Inflate: padding */
124 int MAXRANDHOPS;
125 int BINFILTER; /* filter binary attachments? */
126 int LISTSUPPORTED; /* list supported remailers in remailer-conf reply? */
127 long PACKETEXP; /* Expiration time for old packets */
128 long IDEXP; /* 0 = no ID log !! */
129 long SENDPOOLTIME; /* frequency for sending pool messages */
130
131 char ERRLOG[LINELEN];
132 char ADDRESS[LINELEN];
133 char NAME[LINELEN];
134
135 char ORGANIZATION[LINELEN];
136 char MID[LINELEN];
137
138 /* client config */
139 int NUMCOPIES;
140 char CHAIN[LINELEN];
141 int VERBOSE;
142 int DISTANCE;
143 int MINREL;
144 int RELFINAL;
145 long MAXLAT;
146 char PGPPUBRING[PATHMAX];
147 char PGPSECRING[PATHMAX];
148 char PASSPHRASE[LINELEN];
149 char MAILIN[PATHMAX];
150 char MAILBOX[PATHMAX];
151 char MAILABUSE[PATHMAX];
152 char MAILBLOCK[PATHMAX];
153 char MAILUSAGE[PATHMAX];
154 char MAILANON[PATHMAX];
155 char MAILERROR[PATHMAX];
156 char MAILBOUNCE[PATHMAX];
157
158 static int rereadconfig = 0;
159 static int terminatedaemon = 0;
160
161 #if defined(S_IFDIR) && !defined(S_ISDIR)
162 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
163 #endif
164
165 static int mixdir(char *d, int create)
166 {
167 int err;
168 struct stat buf;
169
170 if (d != MIXDIR)
171 strncpy(MIXDIR, d, PATHMAX);
172 if (MIXDIR[strlen(MIXDIR) - 1] == DIRSEP)
173 MIXDIR[strlen(MIXDIR) - 1] = '\0';
174 err = stat(MIXDIR, &buf);
175 if (err == -1) {
176 if (create) {
177 #ifndef POSIX
178 err = mkdir(MIXDIR);
179 #else
180 err = mkdir(MIXDIR, S_IRWXU);
181 #endif
182 if (err == 0)
183 errlog(NOTICE, "Creating directory %s.\n", MIXDIR);
184 } else
185 err = 1;
186 } else if (!S_ISDIR(buf.st_mode))
187 err = -1;
188 if (err == 0)
189 strcatn(MIXDIR, DIRSEPSTR, PATHMAX);
190 return (err);
191 }
192
193 void whoami(char *addr, char *defaultname)
194 {
195 char *p = NULL;
196
197 #if defined(HAVE_GETDOMAINNAME) || (defined(HAVE_GETHOSTNAME) && ! defined(HAVE_UNAME))
198 char line[LINELEN];
199
200 #endif
201 #ifdef HAVE_UNAME
202 struct utsname uts;
203
204 #endif
205 #ifdef POSIX
206 p = getlogin();
207 #endif
208 if (p == NULL)
209 strcpy(addr, defaultname);
210 else
211 strncpy(addr, p, LINELEN);
212
213 strcatn(addr, "@", LINELEN);
214 #ifdef HAVE_UNAME
215 if (uname(&uts) != -1)
216 strcatn(addr, uts.nodename, LINELEN);
217 #elif defined(HAVE_GETHOSTNAME)
218 if (gethostname(line, LINELEN) == 0)
219 strcatn(addr, line, LINELEN);
220 #endif
221 if (addr[strlen(addr) - 1] == '@')
222 strcatn(addr, SHORTNAME, LINELEN);
223
224 if (strchr(strchr(addr, '@'), '.') == NULL) {
225 #ifdef HAVE_GETDOMAINNAME
226 if (getdomainname(line, LINELEN) == 0 && !streq(line, "(none)")) {
227 strcatn(addr, ".", LINELEN);
228 strcatn(addr, line, LINELEN);
229 }
230 #endif
231 }
232 }
233
234 #define read_conf(t) readconfline(line, #t, sizeof(#t)-1, t)
235
236 static int readconfline(char *line, char *name, int namelen, char *var)
237 {
238 if (strncmp(line, name, namelen) == 0 &&
239 (isspace(line[namelen]) || line[namelen] == '=')) {
240 line += namelen;
241 if (*line == '=')
242 line++;
243 while (isspace(*line))
244 line++;
245 if (line[0] == '\n' || line[0] == '\0') /* leave default */
246 return (1);
247 strncpy(var, line, LINELEN);
248 if (var[strlen(var) - 1] == '\n')
249 var[strlen(var) - 1] = '\0';
250 return (1);
251 } else
252 return (0);
253 }
254
255 #define read_conf_i(t) readiconfline(line, #t, sizeof(#t)-1, &t)
256
257 static int readiconfline(char *line, char *name, int namelen, int *var)
258 {
259 if (strncmp(line, name, namelen) == 0 &&
260 (isspace(line[namelen]) || line[namelen] == '=')) {
261 line += namelen;
262 if (*line == '=')
263 line++;
264 while (isspace(*line))
265 line++;
266 if (line[0] == '\n' || line[0] == '\0') /* leave default */
267 return (1);
268 switch (tolower(line[0])) {
269 case 'n':
270 *var = 0;
271 break;
272 case 'y':
273 *var = 1;
274 break;
275 case 'x':
276 *var = 2;
277 break;
278 default:
279 sscanf(line, "%d", var);
280 }
281 return (1);
282 } else
283 return (0);
284 }
285
286 #define read_conf_t(t) readtconfline(line, #t, sizeof(#t)-1, &t)
287
288 static int readtconfline(char *line, char *name, int namelen, long *var)
289 {
290 char *linenext;
291 int mod = 0;
292 long l = 0;
293 long n;
294
295 if (strncmp(line, name, namelen) == 0 &&
296 (isspace(line[namelen]) || line[namelen] == '=')) {
297 line += namelen;
298 if (*line == '=')
299 line++;
300 for (;; line++) {
301 n = strtol(line, &linenext, 10);
302 if (linenext == line)
303 break;
304 line = linenext;
305 mod = 1;
306 assert(line != NULL);
307 while (isspace(*line))
308 line++;
309 switch (tolower(*line)) {
310 case 'd':
311 l += 24 * 60 * 60 * n;
312 break;
313 case 'm':
314 l += 60 * n;
315 break;
316 case 'h':
317 default:
318 l += 60 * 60 * n;
319 break;
320 }
321 }
322 if (mod)
323 *var = l;
324 return (1);
325 } else
326 return (0);
327 }
328
329 void mix_setdefaults()
330 {
331 #define strnncpy(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a)-1] = '\0'
332
333 strnncpy(MIXCONF , DEFAULT_MIXCONF);
334 strnncpy(DISCLAIMFILE , DEFAULT_DISCLAIMFILE);
335 strnncpy(FROMDSCLFILE , DEFAULT_FROMDSCLFILE);
336 strnncpy(MSGFOOTERFILE, DEFAULT_MSGFOOTERFILE);
337 strnncpy(POP3CONF , DEFAULT_POP3CONF);
338 strnncpy(HELPFILE , DEFAULT_HELPFILE);
339 strnncpy(ABUSEFILE , DEFAULT_ABUSEFILE);
340 strnncpy(REPLYFILE , DEFAULT_REPLYFILE);
341 strnncpy(USAGEFILE , DEFAULT_USAGEFILE);
342 strnncpy(USAGELOG , DEFAULT_USAGELOG);
343 strnncpy(BLOCKFILE , DEFAULT_BLOCKFILE);
344 strnncpy(ADMKEYFILE , DEFAULT_ADMKEYFILE);
345 strnncpy(KEYFILE , DEFAULT_KEYFILE);
346 strnncpy(PGPKEY , DEFAULT_PGPKEY);
347 strnncpy(DSAPARAMS , DEFAULT_DSAPARAMS);
348 strnncpy(DHPARAMS , DEFAULT_DHPARAMS);
349 strnncpy(MIXRAND , DEFAULT_MIXRAND);
350 strnncpy(SECRING , DEFAULT_SECRING);
351 strnncpy(PUBRING , DEFAULT_PUBRING);
352 strnncpy(IDLOG , DEFAULT_IDLOG);
353 strnncpy(STATS , DEFAULT_STATS);
354 strnncpy(DESTBLOCK , DEFAULT_DESTBLOCK);
355 strnncpy(DESTALLOW , DEFAULT_DESTALLOW);
356 strnncpy(SOURCEBLOCK , DEFAULT_SOURCEBLOCK);
357 strnncpy(HDRFILTER , DEFAULT_HDRFILTER);
358 strnncpy(REGULAR , DEFAULT_REGULAR);
359 strnncpy(POOL , DEFAULT_POOL);
360 strnncpy(TYPE1LIST , DEFAULT_TYPE1LIST);
361 strnncpy(TYPE2REL , DEFAULT_TYPE2REL);
362 strnncpy(TYPE2LIST , DEFAULT_TYPE2LIST);
363
364 strnncpy(PGPREMPUBRING, DEFAULT_PGPREMPUBRING);
365 strnncpy(PGPREMPUBASC , DEFAULT_PGPREMPUBASC);
366 strnncpy(PGPREMSECRING, DEFAULT_PGPREMSECRING);
367 strnncpy(NYMSECRING , DEFAULT_NYMSECRING);
368 strnncpy(NYMDB , DEFAULT_NYMDB);
369
370
371 strnncpy(MIXDIR , "");
372 strnncpy(POOLDIR , "");
373
374 /* programs */
375 #ifdef WIN32
376 strnncpy(SENDMAIL , "outfile");
377 #else
378 strnncpy(SENDMAIL , "/usr/lib/sendmail -t");
379 #endif
380 strnncpy(SENDANONMAIL , "");
381 strnncpy(NEWS , "");
382 strnncpy(TYPE1 , "");
383
384 /* addresses */
385 strnncpy(MAILtoNEWS , "mail2news@anon.lcs.mit.edu");
386 strnncpy(REMAILERNAME , "Anonymous Remailer");
387 strnncpy(ANONNAME , "Anonymous");
388 strnncpy(REMAILERADDR , "");
389 strnncpy(ANONADDR , "");
390 strnncpy(COMPLAINTS , "");
391 strnncpy(SMTPRELAY , "");
392 AUTOREPLY = 0;
393
394 #ifdef USE_SOCK
395 strnncpy(HELONAME , "");
396 strnncpy(ENVFROM , "");
397 POP3DEL = 0;
398 POP3SIZELIMIT = 0;
399 POP3TIME = 60 * 60;
400
401 #endif
402
403 strnncpy(SHORTNAME , "");
404
405 /* configuration */
406 REMAIL = 0;
407 MIX = 1;
408 PGP = 1;
409 UNENCRYPTED = 0;
410 REMIX = 1;
411 REPGP = 1;
412
413 POOLSIZE = 0;
414 RATE = 100;
415 MIDDLEMAN = 0;
416 AUTOBLOCK = 1;
417 strnncpy(FORWARDTO, "*");
418 SIZELIMIT = 0; /* maximal size of remailed messages */
419 INFLATEMAX = 50; /* maximal size of Inflate: padding */
420 MAXRANDHOPS = 20;
421 BINFILTER = 0; /* filter binary attachments? */
422 LISTSUPPORTED = 1; /* list supported remailers in remailer-conf reply? */
423 PACKETEXP = 7 * SECONDSPERDAY; /* Expiration time for old packets */
424 IDEXP = 7 * SECONDSPERDAY; /* 0 = no ID log !! */
425 SENDPOOLTIME = 60 * 60; /* frequency for sending pool messages */
426
427 strnncpy(ERRLOG , "");
428 strnncpy(ADDRESS , "");
429 strnncpy(NAME , "");
430
431 strnncpy(ORGANIZATION, "Anonymous Posting Service");
432 strnncpy(MID , "y");
433
434 /* client config */
435 NUMCOPIES = 1;
436 strnncpy(CHAIN, "*,*,*,*");
437 VERBOSE = 2;
438 DISTANCE = 2;
439 MINREL = 98;
440 RELFINAL = 99;
441 MAXLAT = 36 * 60 * 60;
442 strnncpy(PGPPUBRING, "");
443 strnncpy(PGPSECRING, "");
444 #ifdef COMPILEDPASS
445 strnncpy(PASSPHRASE, COMPILEDPASS);
446 #else
447 strnncpy(PASSPHRASE, "");
448 #endif
449 strnncpy(MAILIN , "");
450 strnncpy(MAILBOX , "mbox");
451 strnncpy(MAILABUSE , "");
452 strnncpy(MAILBLOCK , "");
453 #ifdef WIN32
454 strnncpy(MAILUSAGE , "nul:");
455 strnncpy(MAILANON , "nul:");
456 strnncpy(MAILERROR , "nul:");
457 #else
458 strnncpy(MAILUSAGE , "/dev/null");
459 strnncpy(MAILANON , "/dev/null");
460 strnncpy(MAILERROR , "/dev/null");
461 #endif
462 strnncpy(MAILBOUNCE, "");
463 }
464
465 int mix_configline(char *line)
466 {
467 return (read_conf(ADDRESS) || read_conf(NAME) ||
468 read_conf(SHORTNAME) || read_conf(REMAILERADDR) ||
469 read_conf(ANONADDR) || read_conf(REMAILERNAME) ||
470 read_conf(ANONNAME) || read_conf(COMPLAINTS) ||
471 read_conf_i(AUTOREPLY) || read_conf(SMTPRELAY) ||
472 #ifdef USE_SOCK
473 read_conf(HELONAME) || read_conf(ENVFROM) ||
474 #endif
475 read_conf(SENDMAIL) || read_conf(SENDANONMAIL) ||
476 read_conf_i(REMAIL) || read_conf_i(MIX) ||
477 read_conf_i(PGP) || read_conf_i(UNENCRYPTED) ||
478 read_conf_i(REMIX) || read_conf(NEWS) ||
479 read_conf_i(REPGP) ||
480 read_conf(MAILtoNEWS) || read_conf(ERRLOG) ||
481 read_conf(ORGANIZATION) || read_conf(MID) ||
482 read_conf(TYPE1) || read_conf_i(POOLSIZE) ||
483 read_conf_i(RATE) || read_conf_i(MIDDLEMAN) ||
484 read_conf_i(AUTOBLOCK) || read_conf(FORWARDTO) ||
485 read_conf_i(SIZELIMIT) || read_conf_i(INFLATEMAX) ||
486 read_conf_i(MAXRANDHOPS) || read_conf_i(BINFILTER) ||
487 read_conf_i(LISTSUPPORTED) ||
488 read_conf_t(PACKETEXP) || read_conf_t(IDEXP) ||
489 read_conf_t(SENDPOOLTIME) || read_conf_i(NUMCOPIES) ||
490 read_conf(CHAIN) || read_conf_i(VERBOSE) ||
491 read_conf_i(DISTANCE) || read_conf_i(MINREL) ||
492 read_conf_i(RELFINAL) || read_conf_t(MAXLAT) ||
493 read_conf(PGPPUBRING) || read_conf(PGPSECRING) ||
494 read_conf(PASSPHRASE) ||
495 #ifdef USE_SOCK
496 read_conf_i(POP3DEL) || read_conf_i(POP3SIZELIMIT) ||
497 read_conf_t(POP3TIME) ||
498 #endif
499 read_conf(MAILBOX) || read_conf(MAILABUSE) ||
500 read_conf(MAILBLOCK) || read_conf(MAILUSAGE) ||
501 read_conf(MAILANON) || read_conf(MAILERROR) ||
502 read_conf(MAILBOUNCE) || read_conf(MAILIN) ||
503
504 read_conf(DISCLAIMFILE) || read_conf(FROMDSCLFILE) ||
505 read_conf(MSGFOOTERFILE) ||
506 read_conf(POP3CONF) || read_conf(HELPFILE) ||
507 read_conf(ABUSEFILE) || read_conf(REPLYFILE) ||
508 read_conf(USAGEFILE) || read_conf(USAGELOG) ||
509 read_conf(BLOCKFILE) || read_conf(ADMKEYFILE) ||
510 read_conf(KEYFILE) || read_conf(PGPKEY) ||
511 read_conf(DSAPARAMS) || read_conf(DHPARAMS) ||
512 read_conf(MIXRAND) || read_conf(SECRING) ||
513 read_conf(PUBRING) || read_conf(IDLOG) ||
514 read_conf(STATS) || read_conf(DESTBLOCK) ||
515 read_conf(DESTALLOW) || read_conf(SOURCEBLOCK) ||
516 read_conf(HDRFILTER) || read_conf(REGULAR) ||
517 read_conf(POOL) || read_conf(TYPE1LIST) ||
518 read_conf(TYPE2REL) || read_conf(TYPE2LIST) ||
519 read_conf(PGPREMPUBRING) || read_conf(PGPREMPUBASC) ||
520 read_conf(PGPREMSECRING) || read_conf(NYMSECRING) ||
521 read_conf(NYMDB) );
522 }
523
524 static int mix_config(void)
525 {
526 char *d;
527 FILE *f;
528 char line[PATHMAX];
529 int err = -1;
530 #ifdef POSIX
531 struct passwd *pw;
532 #endif
533 struct stat buf;
534 #ifdef HAVE_UNAME
535 struct utsname uts;
536 #endif
537 #ifdef WIN32
538 HKEY regsw, reg, regpgp;
539 DWORD type, len;
540 int rkey = 0;
541 #endif
542
543 mix_setdefaults();
544
545 #ifdef POSIX
546 pw = getpwuid(getuid());
547 #endif
548
549 #ifdef WIN32
550 RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &regsw);
551 len=sizeof(line);
552 if (err == -1 &&
553 RegOpenKeyEx(regsw, "Mixmaster", 0, KEY_QUERY_VALUE, &reg) == 0) {
554 if (RegQueryValueEx(reg, "MixDir", 0, &type, line, &len) == 0)
555 err = mixdir(line, 1);
556 RegCloseKey(reg);
557 }
558 #endif
559
560 if (err == -1 && (d = getenv("MIXPATH")) != NULL)
561 err = mixdir(d, 1);
562
563 #ifdef SPOOL
564 if (err == -1 && strlen(SPOOL) > 0)
565 err = mixdir(SPOOL, 0);
566 #endif
567
568 #ifdef POSIX
569 if (err == -1 && pw != NULL) {
570 strncpy(line, pw->pw_dir, PATHMAX);
571 line[PATHMAX-1] = '\0';
572 if (line[strlen(line) - 1] != DIRSEP)
573 strcatn(line, DIRSEPSTR, PATHMAX);
574 strcatn(line, HOMEMIXDIR, PATHMAX);
575 err = mixdir(line, 1);
576 }
577 #endif
578
579 if (err == -1) {
580 getcwd(MIXDIR, PATHMAX);
581 mixdir(MIXDIR, 0);
582 }
583
584 mixfile(POOLDIR, POOL);
585 if (POOLDIR[strlen(POOLDIR) - 1] == DIRSEP)
586 POOLDIR[strlen(POOLDIR) - 1] = '\0';
587 if (stat(POOLDIR, &buf) != 0)
588 if
589 #ifndef POSIX
590 (mkdir(POOLDIR) != 0)
591 #else
592 (mkdir(POOLDIR, S_IRWXU) == -1)
593 #endif
594 strncpy(POOLDIR, MIXDIR, PATHMAX);
595
596 #ifdef GLOBALMIXCONF
597 f = mix_openfile(GLOBALMIXCONF, "r");
598 if (f != NULL) {
599 while (fgets(line, LINELEN, f) != NULL)
600 if (line[0] > ' ' && line[0] != '#')
601 mix_configline(line);
602 fclose(f);
603 }
604 #endif
605 f = mix_openfile(MIXCONF, "r");
606 if (f != NULL) {
607 while (fgets(line, LINELEN, f) != NULL)
608 if (line[0] > ' ' && line[0] != '#')
609 mix_configline(line);
610 fclose(f);
611 }
612 if (IDEXP > 0 && IDEXP < 5 * SECONDSPERDAY)
613 IDEXP = 5 * SECONDSPERDAY;
614 if (MAXRANDHOPS > 20)
615 MAXRANDHOPS = 20;
616
617 if (strchr(SHORTNAME, '.'))
618 *strchr(SHORTNAME, '.') = '\0';
619 if (strchr(SHORTNAME, ' '))
620 *strchr(SHORTNAME, ' ') = '\0';
621 #ifdef HAVE_UNAME
622 if (SHORTNAME[0] == '\0' && uname(&uts) != -1)
623 strncpy(SHORTNAME, uts.nodename, LINELEN);
624 #elif defined(HAVE_GETHOSTNAME)
625 if (SHORTNAME[0] == '\0')
626 gethostname(SHORTNAME, LINELEN);
627 #endif
628 if (SHORTNAME[0] == '\0')
629 strcpy(SHORTNAME, "unknown");
630
631 if (ADDRESS[0] == '\0')
632 whoami(ADDRESS, "user");
633
634 #ifdef HAVE_GECOS
635 if (NAME[0] == '\0' && pw != NULL)
636 strcatn(NAME, pw->pw_gecos, sizeof(NAME));
637 #endif
638
639 if (REMAILERADDR[0] == '\0')
640 strncpy(REMAILERADDR, ADDRESS, LINELEN);
641
642 if (COMPLAINTS[0] == '\0')
643 strncpy(COMPLAINTS, REMAILERADDR, LINELEN);
644
645 if (strchr(REMAILERNAME, '@') == NULL) {
646 strcatn(REMAILERNAME, " <", LINELEN);
647 strcatn(REMAILERNAME, REMAILERADDR, LINELEN);
648 strcatn(REMAILERNAME, ">", LINELEN);
649 }
650 if (strchr(ANONNAME, '@') == NULL && ANONADDR[0] != '\0') {
651 strcatn(ANONNAME, " <", LINELEN);
652 strcatn(ANONNAME, ANONADDR, LINELEN);
653 strcatn(ANONNAME, ">", LINELEN);
654 }
655 if (strchr(ANONNAME, '@') == NULL) {
656 strcatn(ANONNAME, " <", LINELEN);
657 strcatn(ANONNAME, REMAILERADDR, LINELEN);
658 strcatn(ANONNAME, ">", LINELEN);
659 }
660 #ifndef USE_PGP
661 if (TYPE1[0] == '\0')
662 PGP = 0;
663 #endif
664 #ifndef USE_RSA
665 MIX = 0;
666 #endif
667
668 #ifdef WIN32
669 if (RegOpenKeyEx(regsw, "PGP", 0, KEY_ALL_ACCESS, &regpgp) == 0)
670 rkey++;
671 if (rkey && RegOpenKeyEx(regpgp, "PGPlib", 0, KEY_QUERY_VALUE, &reg) == 0)
672 rkey++;
673 if (PGPPUBRING[0] == '\0' && rkey == 2) {
674 len = PATHMAX;
675 RegQueryValueEx(reg, "PubRing", 0, &type, PGPPUBRING, &len);
676 }
677 if (PGPSECRING[0] == '\0' && rkey == 2) {
678 len = PATHMAX;
679 RegQueryValueEx(reg, "SecRing", 0, &type, PGPSECRING, &len);
680 }
681 if (rkey == 2)
682 RegCloseKey(reg);
683 if (rkey)
684 RegCloseKey(regpgp);
685 RegCloseKey(regsw);
686 #endif
687
688 if (PGPPUBRING[0] == '\0') {
689 char *d;
690
691 if ((d = getenv("HOME")) != NULL) {
692 strcpy(PGPPUBRING, d);
693 strcatn(PGPPUBRING, "/.pgp/", PATHMAX);
694 }
695 strcatn(PGPPUBRING, "pubring.pkr", PATHMAX);
696 if (stat(PGPPUBRING, &buf) == -1)
697 strcpy(strrchr(PGPPUBRING, '.'), ".pgp");
698 }
699 if (PGPSECRING[0] == '\0') {
700 char *d;
701
702 if ((d = getenv("HOME")) != NULL) {
703 strcpy(PGPSECRING, d);
704 strcatn(PGPSECRING, "/.pgp/", PATHMAX);
705 }
706 strcatn(PGPSECRING, "secring.skr", PATHMAX);
707 if (stat(PGPSECRING, &buf) == -1)
708 strcpy(strrchr(PGPSECRING, '.'), ".pgp");
709 }
710 if (streq(NEWS, "mail-to-news"))
711 strncpy(NEWS, MAILtoNEWS, sizeof(NEWS));
712
713 if (f == NULL) {
714 #ifndef GLOBALMIXCONF
715 /* Only write the config file in non systemwide installation */
716 f = mix_openfile(MIXCONF, "w");
717 if (f == NULL)
718 errlog(WARNING, "Can't open %s%s!\n", MIXDIR, MIXCONF);
719 else {
720 fprintf(f, "# mix.cfg - mixmaster configuration file\n");
721 fprintf(f, "NAME %s\n", NAME);
722 fprintf(f, "ADDRESS %s\n", ADDRESS);
723 fprintf(f, "\n# edit to set up a remailer:\n");
724 fprintf(f, "REMAIL n\n");
725 fprintf(f, "SHORTNAME %s\n", SHORTNAME);
726 fprintf(f, "REMAILERADDR %s\n", REMAILERADDR);
727 fprintf(f, "COMPLAINTS %s\n", COMPLAINTS);
728 fclose(f);
729 }
730 #endif
731 REMAIL = 0;
732 }
733
734 return (0);
735 }
736
737 /** Library initialization: ******************************************/
738
739 static int initialized = 0;
740
741 int mix_init(char *mixdir)
742 {
743 if (!initialized) {
744 if (mixdir)
745 strncpy(MIXDIR, mixdir, LINELEN);
746 mix_config();
747 #if defined(USE_SOCK) && defined(WIN32)
748 sock_init();
749 #endif
750 /* atexit (mix_exit); */
751 initialized = 1;
752 }
753
754 if (rnd_init() == -1)
755 rnd_seed();
756 return(0);
757 }
758
759 void mix_exit(void)
760 {
761 if (!initialized)
762 return;
763 rnd_final();
764 #if defined(USE_SOCK) && defined(WIN32)
765 sock_exit();
766 #endif
767 initialized=0;
768 }
769
770 int mix_regular(int force)
771 {
772 FILE *f;
773 long now, tpool = 0, tpop3 = 0, tdaily = 0;
774 int ret = 0;
775
776 mix_init(NULL);
777 now = time(NULL);
778
779 f = mix_openfile(REGULAR, "r+");
780 if (f != NULL) {
781 lock(f);
782 fscanf(f, "%ld %ld %ld", &tpool, &tpop3, &tdaily);
783 if (now - tpool >= SENDPOOLTIME)
784 force |= FORCE_POOL;
785 #ifdef USE_SOCK
786 if (now - tpop3 >= POP3TIME)
787 force |= FORCE_POP3;
788 #endif
789 if (now - tdaily >= SECONDSPERDAY)
790 force |= FORCE_DAILY;
791 if (force & FORCE_POOL)
792 tpool = now;
793 if (force & FORCE_POP3)
794 tpop3 = now;
795 if (force & FORCE_DAILY)
796 tdaily = now;
797 rewind(f);
798 fprintf(f, "%ld %ld %ld\n", tpool, tpop3, tdaily);
799 unlock(f);
800 fclose(f);
801 } else {
802 force = FORCE_POOL | FORCE_POP3 | FORCE_DAILY;
803 f = mix_openfile(REGULAR, "w+");
804 if (f != NULL) {
805 lock(f);
806 fprintf(f, "%ld %ld %ld\n", now, now, now);
807 unlock(f);
808 fclose(f);
809 } else
810 errlog(ERRORMSG, "Can't create %s!\n", REGULAR);
811 }
812
813 if (force & FORCE_DAILY)
814 mix_daily(), ret = 1;
815 #ifdef USE_SOCK
816 if (force & FORCE_POP3)
817 pop3get();
818 #endif
819 if (force & FORCE_POOL)
820 ret = pool_send();
821
822 return (ret);
823 }
824
825 int mix_daily(void)
826 {
827 idexp();
828 pool_packetexp();
829 stats(NULL);
830 keymgt(0);
831 return (0);
832 }
833
834 /** Handle signals SIGHUP, SIGINT, and SIGTERM
835 This signal handler gets called if the daemon
836 process receives one of SIGHUP, SIGINT, or SIGTERM.
837 It then sets either rereadconfig of terminatedaemon
838 to true depending on the signal received.
839
840 @author PP
841 @return nothing
842 */
843 void sighandler(int signal) {
844 if (signal == SIGHUP)
845 rereadconfig = 1;
846 else if (signal == SIGINT || signal == SIGTERM)
847 terminatedaemon = 1;
848 };
849
850 /** Set the signal handler for SIGHUP, SIGINT and SIGTERM
851 This function registers signal handlers so that
852 we can react on signals send by the user in daemon
853 mode. SIGHUP will instruct mixmaster to reload its
854 configuration while SIGINT and SIGTERM will instruct
855 it to shut down. Mixmaster will finish the current
856 pool run before it terminates.
857
858 @param restart Whether or not system calls should be
859 restarted. Usually we want this, the
860 only excetion is the sleep() in the
861 daemon mail loop.
862 @author PP
863 @return -1 if calling sigaction failed, 0 on
864 no error
865 */
866 int setsignalhandler(int restart)
867 {
868 #ifdef POSIX
869 struct sigaction hdl;
870 int err = 0;
871
872 memset(&hdl, 0, sizeof(hdl));
873 hdl.sa_handler = sighandler;
874 hdl.sa_flags = restart ? SA_RESTART : 0;
875
876 if (sigaction(SIGHUP, &hdl, NULL))
877 err = -1;
878 if (sigaction(SIGINT, &hdl, NULL))
879 err = -1;
880 if (sigaction(SIGTERM, &hdl, NULL))
881 err = -1;
882 return (err);
883 #else /* POSIX */
884 return(0);
885 #endif /* POSIX */
886 }
887
888 #ifdef WIN32
889 /* Try to detect if we are the service or not...
890 seems there is no easy reliable way */
891 int is_nt_service(void)
892 {
893 static int issvc = -1;
894 #ifdef WIN32SERVICE
895 STARTUPINFO StartupInfo;
896 OSVERSIONINFO VersionInfo;
897 DWORD dwsize;
898
899 if (issvc != -1) /* do it only once */
900 return issvc;
901
902 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
903 if (GetVersionEx(&VersionInfo))
904 if (VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
905 return issvc = 0; /* not NT - not the service */
906
907 if (!GetConsoleTitle(&VersionInfo,sizeof(VersionInfo)))
908 /* reuse VersionInfo to save memory */
909 return issvc = 1; /* have no console - we are the service probably */
910
911 GetStartupInfo(&StartupInfo);
912 if (StartupInfo.lpDesktop[0] == 0)
913 return issvc = 1; /* have no desktop - we are the service probably */
914
915 if (_fileno(stdin) == -1 && _fileno(stdout) == -1 && _fileno(stderr) == -1)
916 return issvc = 1; /* have no stdin,stderr,stdout - probably service */
917 #endif // WIN32SERVICE
918
919 return issvc = 0; // assume not the service
920 } // is_nt_service
921
922 HANDLE hMustTerminate = NULL;
923 void set_nt_exit_event(HANDLE h_svc_exit_event)
924 {
925 hMustTerminate = h_svc_exit_event;
926 } // set_nt_exit_event
927
928 #endif // WIN32
929
930 int mix_daemon(void)
931 {
932 long t, slept;
933 t = SENDPOOLTIME;
934 #ifdef USE_SOCK
935 if (POP3TIME < t)
936 t = POP3TIME;
937 #endif
938 slept = t;
939
940 setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
941 for(;;) {
942 if (terminatedaemon)
943 exit(0);
944 if (rereadconfig) {
945 rereadconfig = 0;
946 mix_config();
947 t = SENDPOOLTIME;
948 #ifdef USE_SOCK
949 if (POP3TIME < t)
950 t = POP3TIME;
951 #endif
952 }
953 if (slept >= t) {
954 mix_regular(0);
955 slept = 0;
956 }
957
958 if (!terminatedaemon && !rereadconfig) {
959 setsignalhandler(0); /* set signal handlers; don't restart system calls */
960 #ifdef WIN32
961 #ifdef WIN32SERVICE
962 if (hMustTerminate) {
963 if (WaitForSingleObject(hMustTerminate, t * 1000) == WAIT_OBJECT_0) {
964 CloseHandle(hMustTerminate);
965 return 0;
966 }
967 } else
968 #endif
969 Sleep(t * 1000);
970 #else
971 slept += (t - slept) - sleep(t - slept);
972 #endif
973 setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
974 }
975 }
976 }
977
978 /** error ***************************************************************/
979
980 void errlog(int type, char *fmt,...)
981 {
982 va_list args;
983 BUFFER *msg;
984 FILE *e = NULL;
985 time_t t;
986 struct tm *tc;
987 char line[LINELEN];
988 int p;
989 char err[6][8] =
990 {"", "Error", "Warning", "Notice", "Info", "Info"};
991
992 if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2)
993 || (type == DEBUGINFO && VERBOSE < 3))
994 return;
995
996 t = time(NULL);
997 tc = localtime(&t);
998 strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc);
999
1000 msg = buf_new();
1001 buf_appends(msg, line);
1002 p = msg->length;
1003 buf_appendf(msg, "%s: ", err[type]);
1004 va_start(args, fmt);
1005 buf_vappendf(msg, fmt, args);
1006 va_end(args);
1007
1008 if (streq(ERRLOG, "stdout"))
1009 e = stdout;
1010 else if (streq(ERRLOG, "stderr"))
1011 e = stderr;
1012
1013 if (e == NULL && (ERRLOG[0] == '\0' ||
1014 (e = mix_openfile(ERRLOG, "a")) == NULL))
1015 mix_status("%s", msg->data + p);
1016 else {
1017 buf_write(msg, e);
1018 if (e != stderr && e != stdout) {
1019 fclose(e);
1020 /* duplicate the error message on screen */
1021 mix_status("%s", msg->data + p);
1022 }
1023 }
1024 buf_free(msg);
1025 }
1026
1027 static char statusline[BUFSIZE] = "";
1028
1029 void mix_status(char *fmt,...)
1030 {
1031 va_list args;
1032
1033 if (fmt != NULL) {
1034 va_start(args, fmt);
1035 #ifdef _MSC
1036 _vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
1037 #else
1038 vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
1039 #endif
1040 va_end(args);
1041 }
1042 #ifdef USE_NCURSES
1043 if (menu_initialized) {
1044 cl(LINES - 2, 10);
1045 printw("%s", statusline);
1046 refresh();
1047 } else
1048 #endif
1049 {
1050 fprintf(stderr, "%s", statusline);
1051 }
1052 }
1053
1054 void mix_genericerror(void)
1055 {
1056 if (streq(statusline, "") || strfind(statusline, "...") ||
1057 strifind(statusline, "generating"))
1058 mix_status("Failed!");
1059 else
1060 mix_status(NULL);
1061 }

  ViewVC Help
Powered by ViewVC 1.1.5