tmain.c - mixmaster - mixmaster 3.0 patched for libressl
HTML git clone git://parazyd.org/mixmaster.git
DIR Log
DIR Files
DIR Refs
DIR README
---
tmain.c (22681B)
---
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 Anonymizer Inc. and others.
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 Command-line based frontend
9 $Id: main.c 937 2006-06-24 15:52:20Z colin $ */
10
11
12 #include "mix3.h"
13 #include "pgp.h"
14 #include <stdio.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <stdlib.h>
18 #ifdef POSIX
19 #include <unistd.h>
20 #else /* end of POSIX */
21 #include <io.h>
22 #endif /* else if not POSIX */
23 #include <assert.h>
24
25 static char *largopt(char *p, char *opt, char *name, int *error);
26 static void noarg(char *name, char p);
27 static int check_get_pass(int force, int never_ask_for_passphrase);
28
29 /** main *****************************************************************/
30
31 /* Returns:
32 0 successful operation
33 1 command line error
34 2 client error condition */
35
36 #ifdef WIN32SERVICE
37 int mix_main(int argc, char *argv[])
38 #else
39 int main(int argc, char *argv[])
40 #endif /* WIN32SERVICE */
41 {
42 int error = 0, deflt = 1, help = 0, readmail = 0, send = -1, sendpool = 0,
43 header = 1, maint = 0, keygen = 0, verbose = 0, sign = 0, encrypt = 0,
44 redirect_mail = 0, about=0, version=0;
45 int daemon = 0, type_list = 0, nodetach = 0;
46 int update_stats = 0, update_pingerlist = 0;
47 int never_ask_for_passphrase = 0;
48
49 #ifdef USE_SOCK
50 int pop3 = 0;
51
52 #endif /* USE_SOCK */
53 char *filename = NULL;
54 int i;
55 int ret = 0;
56 char *p, *q;
57 char chain[1024] = "";
58 char nym[LINELEN] = "";
59 BUFFER *nymopt, *pseudonym, *attachments, *statssrc;
60 int numcopies = 0; /* default value set in mix.cfg */
61 BUFFER *msg, *chainlist, *field, *content;
62 FILE *f;
63 char pingpath[PATHMAX];
64
65 /* Check if parse_yearmonthday works */
66 assert(parse_yearmonthday("2003-04-01") == 1049155200);
67
68 mix_init(NULL);
69
70 msg = buf_new();
71 chainlist = buf_new();
72 nymopt = buf_new();
73 pseudonym = buf_new();
74 attachments = buf_new();
75 field = buf_new();
76 content = buf_new();
77 statssrc = buf_new();
78
79 #ifdef USE_NCURSES
80 if (argc == 1) {
81 if (isatty(fileno(stdin)))
82 menu_main();
83 else
84 menu_folder(0, NULL);
85 goto clientpool;
86 }
87 #endif /* USE_NCURSES */
88 if (argc > 1 && strleft(argv[1], "-f")) {
89 menu_folder(strlen(argv[1]) > 2 ? argv[1][2] : 0, argc < 3 ? NULL : argv[2]);
90 goto clientpool;
91 }
92 for (i = 1; i < argc; i++) {
93 p = argv[i];
94 if (p[0] == '-' && p[1] != '\0') {
95 if (p[1] == '-') {
96 p += 2;
97 if (strieq(p, "help"))
98 help = 1, deflt = 0;
99 else if (streq(p, "version"))
100 version = 1, deflt = 0;
101 else if (streq(p, "about"))
102 about = 1, deflt = 0;
103 else if (streq(p, "verbose"))
104 verbose = 1;
105 else if (streq(p, "type-list"))
106 type_list = 1;
107 else if (streq(p, "dummy"))
108 send = MSG_NULL, deflt = 0;
109 else if (streq(p, "remailer"))
110 maint = 1, deflt = 0;
111 else if (streq(p, "generate-key"))
112 keygen = 2, deflt = 0;
113 else if (streq(p, "update-keys"))
114 keygen = 1, deflt = 0;
115 else if (streq(p, "send"))
116 sendpool = 1, deflt = 0;
117 else if (streq(p, "read-mail"))
118 readmail = 1, deflt = 0;
119 else if (streq(p, "redirect"))
120 redirect_mail = 1, deflt = 0;
121 else if (streq(p, "store-mail"))
122 readmail = 2, deflt = 0;
123 #ifdef USE_SOCK
124 else if (streq(p, "pop-mail"))
125 pop3 = 1, deflt = 0;
126 #endif /* USE_SOCK */
127 else if (streq(p, "daemon"))
128 daemon = 1, deflt = 0;
129 else if (streq(p, "no-detach"))
130 nodetach = 1;
131 else if (streq(p, "post"))
132 send = MSG_POST;
133 else if (streq(p, "mail"))
134 send = MSG_MAIL;
135 else if (streq(p, "sign"))
136 sign = 1;
137 else if (streq(p, "encrypt"))
138 encrypt = 1;
139 else if (streq(p, "no-ask-passphrase"))
140 never_ask_for_passphrase = 1;
141 else if (streq(p, "update-pinger-list"))
142 update_pingerlist = 1;
143 else if (streq(p, "update-stats")) {
144 buf_clear(statssrc);
145 f = mix_openfile(STATSSRC, "r");
146 if (f != NULL) {
147 buf_read(statssrc, f);
148 fclose(f);
149 }
150 if (statssrc->length > 0) {
151 update_stats = 1;
152 } else {
153 deflt = 0;
154 fprintf(stderr, "%s: No current stats source --%s\n", argv[0], p);
155 }
156 } else if (strleft(p, "update-stats") && p[strlen("update-stats")] == '=') {
157 buf_clear(statssrc);
158 buf_appendf(statssrc, "%s", (p + strlen("update-stats") + 1));
159 if (statssrc->length > 0) {
160 update_stats = 1;
161 } else {
162 fprintf(stderr, "%s: No stats source specified --%s\n", argv[0], p);
163 }
164 } else if ((q = largopt(p, "to", argv[0], &error)) != NULL) {
165 header = 0;
166 buf_appendf(msg, "To: %s\n", q);
167 } else if ((q = largopt(p, "post-to", argv[0], &error)) != NULL) {
168 send = MSG_POST, header = 0;
169 buf_appendf(msg, "Newsgroups: %s\n", q);
170 } else if ((q = largopt(p, "subject", argv[0], &error)) != NULL) {
171 buf_appendf(msg, "Subject: %s\n", q);
172 } else if ((q = largopt(p, "header", argv[0], &error)) != NULL) {
173 buf_appendf(msg, "%s\n", q);
174 } else if ((q = largopt(p, "chain", argv[0], &error)) != NULL) {
175 buf_appendf(msg, "Chain: %s\n", q);
176 }
177 #ifdef USE_PGP
178 else if ((q = largopt(p, "reply-chain", argv[0], &error)) != NULL) {
179 buf_appendf(msg, "Reply-Chain: %s\n", q);
180 } else if ((q = largopt(p, "latency", argv[0], &error)) != NULL) {
181 buf_appendf(msg, "Latency: %s\n", q);
182 } else if ((q = largopt(p, "attachment", argv[0], &error)) != NULL) {
183 buf_appendf(attachments, "%s\n", q);
184 #ifdef NYMSUPPORT
185 } else if ((q = largopt(p, "nym-config", argv[0], &error)) != NULL) {
186 deflt = 0;
187 strncpy(nym, q, sizeof(nym));
188 if (i > argc && strileft(argv[i + 1], "name="))
189 buf_sets(pseudonym, argv[++i] + 5);
190 else if (i > argc && strileft(argv[i + 1], "opt="))
191 buf_appends(nymopt, argv[++i] + 5);
192 } else if ((q = largopt(p, "nym", argv[0], &error)) != NULL) {
193 buf_appendf(msg, "Nym: %s\n", q);
194 #endif /* NYMSUPPORT */
195 }
196 #endif /* USE_PGP */
197 else if ((q = largopt(p, "copies", argv[0], &error)) != NULL) {
198 sscanf(q, "%d", &numcopies);
199 } else if ((q = largopt(p, "config", argv[0], &error)) != NULL) {
200 strncpy(MIXCONF, q, PATHMAX);
201 MIXCONF[PATHMAX-1] = 0;
202 mix_config(); /* configuration file changed - reread it */
203 } else if (error == 0 && mix_configline(p) == 0) {
204 fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]);
205 error = 1;
206 }
207 } else {
208 while (*++p) {
209 switch (*p) {
210 case 'd':
211 send = MSG_NULL, deflt = 0;
212 break;
213 case 'R':
214 readmail = 1, deflt = 0;
215 break;
216 case 'I':
217 readmail = 2, deflt = 0;
218 break;
219 case 'S':
220 sendpool = 1, deflt = 0;
221 break;
222 case 'M':
223 maint = 1, deflt = 0;
224 break;
225 #ifdef USE_SOCK
226 case 'P':
227 pop3 = 1, deflt = 0;
228 break;
229 #endif /* USE_SOCK */
230 case 'D':
231 daemon = 1, deflt = 0;
232 break;
233 case 'G':
234 keygen = 2, deflt = 0;
235 break;
236 case 'K':
237 keygen = 1, deflt = 0;
238 break;
239 case 'L': /* backwards compatibility */
240 break;
241 case 'v':
242 verbose = 1;
243 break;
244 case 'h':
245 help = 1, deflt = 0;
246 break;
247 case 'T':
248 type_list = 1;
249 break;
250 case 'V':
251 version = 1, deflt = 0;
252 break;
253 case 't':
254 if (*(p + 1) == 'o')
255 p++;
256 header = 0;
257 if (i < argc - 1)
258 buf_appendf(msg, "To: %s\n", argv[++i]);
259 else {
260 fprintf(stderr, "%s: Missing argument for option -to\n", argv[0]);
261 error = 1;
262 }
263 break;
264 case 's':
265 if (i < argc - 1)
266 buf_appendf(msg, "Subject: %s\n", argv[++i]);
267 else {
268 noarg(argv[0], *p);
269 error = 1;
270 }
271 break;
272 case 'l':
273 if (i < argc - 1)
274 buf_appendf(msg, "Chain: %s\n", argv[++i]);
275 else {
276 noarg(argv[0], *p);
277 error = 1;
278 }
279 break;
280 case 'r':
281 if (i < argc - 1)
282 buf_appendf(msg, "Reply-Chain: %s\n", argv[++i]);
283 else {
284 noarg(argv[0], *p);
285 error = 1;
286 }
287 break;
288 #ifdef USE_PGP
289 case 'n':
290 if (i < argc - 1)
291 buf_appendf(msg, "Nym: %s\n", argv[++i]);
292 else {
293 noarg(argv[0], *p);
294 error = 1;
295 }
296 break;
297 #endif /* USE_PGP */
298 case 'c':
299 if (i < argc - 1)
300 sscanf(argv[++i], "%d", &numcopies);
301 else {
302 noarg(argv[0], *p);
303 error = 1;
304 }
305 break;
306 case 'p':
307 send = MSG_POST;
308 break;
309 case 'g':
310 if (i < argc - 1) {
311 send = MSG_POST, header = 0;
312 buf_appendf(msg, "Newsgroups: %s\n", argv[++i]);
313 } else {
314 noarg(argv[0], *p);
315 error = 1;
316 }
317 break;
318 case 'a':
319 if (i < argc - 1)
320 buf_appendf(attachments, "%s\n", argv[++i]);
321 else {
322 noarg(argv[0], *p);
323 error = 1;
324 }
325 break;
326 case 'm':
327 send = MSG_MAIL;
328 break;
329 default:
330 fprintf(stderr, "%s: Invalid option -%c\n", argv[0], *p);
331 error = 1;
332 break;
333 }
334 }
335 }
336 } else {
337 if (strchr(argv[i], '@')) {
338 header = 0;
339 buf_appendf(msg, "To: %s\n", argv[i]);
340 } else {
341 if (filename == NULL)
342 filename = argv[i];
343 else {
344 fprintf(stderr, "%s: Error in command line: %s\n", argv[0], argv[i]);
345 error = 1;
346 }
347 }
348 }
349 }
350
351 if (error) {
352 ret = 1;
353 goto end;
354 }
355
356 if (type_list) {
357 BUFFER *type2list;
358 type2list = buf_new();
359 if (prepare_type2list(type2list) < 0) {
360 fprintf(stderr, "Cannot print type2.list.\n");
361 ret = 2;
362 } else {
363 printf("%s", type2list->data);
364 };
365 buf_free(type2list);
366 goto end;
367 }
368
369 if (version) {
370 printf("Mixmaster %s\n", VERSION);
371 ret = 0;
372 goto end;
373 }
374
375 if (update_pingerlist) {
376 mixfile(pingpath, ALLPINGERSFILE);
377 if (verbose) printf ("downloading %s...\n", ALLPINGERSURL);
378 if (url_download(ALLPINGERSURL, pingpath) < 0) {
379 printf(" Download failed... Try again later.\n");
380 errlog(ERRORMSG, "All Pingers File Download failed.\n");
381 } else {
382 if (verbose) printf(" Done.\n");
383 errlog(LOG, "All Pingers File Downloaded OK.\n");
384 }
385 ret = 0;
386 goto end;
387 }
388
389 if (update_stats) {
390 ret = download_stats(statssrc->data);
391 if (ret == -3) {
392 fprintf(stderr, "Stats source does not include all required files.\n");
393 } else if (ret == -2) {
394 fprintf(stderr, "Could not open stats source file for writing\n");
395 } else if (ret == -1) {
396 fprintf(stderr, "Stats source download failed.\n");
397 }
398 ret = 0;
399 goto end;
400 }
401
402 #ifdef USE_NCURSES
403 /* If we get here then it's possible we still want to use the NCURSES interface */
404 if (deflt && (send == -1) && isatty(fileno(stdin))) {
405 menu_main();
406 goto clientpool;
407 }
408 #endif /* USE_NCURSES */
409
410 if (help ||about ||(isatty(fileno(stdin)) && isatty(fileno(stdout))))
411 fprintf(stderr, "Mixmaster %s\n", VERSION);
412 if (help ||about)
413 printf("\n\n");
414 if (about) {
415 printf("Many people have contributed to the source code for Mixmaster.\n");
416 printf("These contributors include:\n\n");
417 printf("Lance Cottrell\n");
418 printf("Janis Jagars\n");
419 printf("Ulf Moeller\n");
420 printf("Peter Palfrader\n");
421 printf("Len Sassaman\n");
422 printf("\nand others. For full information on copyright and license issues,\n");
423 printf("read the bundled file COPYRIGHT.\n\n");
424 ret = 0;
425 goto end;
426 }
427
428 if (help) {
429 printf("Usage: %s [options] [user@host] [filename]\n\n", argv[0]);
430 printf("Options:\n\
431 \n\
432 -h, --help summary of command line options\n\
433 -V, --version print version information\n\
434 --about print authorship information\n\
435 -T, --type-list list available remailers\n\
436 -t, --to=user@host the recipient's address(es)\n\
437 -g, --post-to=newsgroup newsgroup(s) to post to\n\
438 -p, --post input is a Usenet article\n\
439 -m, --mail input is a mail message\n\
440 -s, --subject=subject message subject\n\
441 --header='header line' arbitrary message headers\n\
442 -a, --attachment=file attach a file\n"
443 #ifdef USE_PGP
444 #ifdef NYMSUPPORT
445 "-n, --nym=yournym use pseudonym to send the message\n"
446 #endif /* NYMSUPPORT */
447 " --encrypt encrypt the message using the PGP format\n\
448 --sign sign the message using the PGP format\n"
449 #endif /* USE_PGP */
450 "-l, --chain=mix1,mix2,mix3,... specify a remailer chain\n\
451 -c, --copies=num send num copies to increase reliability\n\
452 -d, --dummy generate a dummy message\n\
453 -S, --send send the message(s) in the pool\n"
454 #ifdef USE_PGP
455 #ifdef NYMSUPPORT
456 " --nym-config=yournym generate a new pseudonym\n\
457 --latency=hours reply chain latency\n\
458 --reply-chain=rem1,rem2,... reply chain for the pseudonym\n"
459 #endif /* NYMSUPPORT */
460 #endif /* USE_PGP */
461 "-v, --verbose output informational messages\n\
462 -f [file] read a mail folder\n\
463 --update-pinger-list Download an updated all pingers list file\n\
464 --update-stats[=source] Download updated stats\n"
465
466 #ifndef USE_NCURSES
467 "\n-fr, -ff, -fg [file] send reply/followup/group reply to a message\n"
468 #endif /* USE_NCURSES */
469 "\nThe input file is expected to contain mail headers if no address is\n\
470 specified in the command line.\n\
471 \n\
472 Remailer:\n\
473 \n\
474 -R, --read-mail read remailer message from stdin\n\
475 -I, --store-mail read remailer msg from stdin, do not decrypt\n\
476 -M, --remailer process the remailer pool\n\
477 -D, --daemon remailer as background process\n\
478 --no-detach do not detach from terminal as daemon\n"
479 #ifdef USE_SOCK
480 "-S, --send force sending messages from the pool\n"
481 #endif /* USE_SOCK */
482 "-P, --pop-mail force getting messages from POP3 servers\n\
483 -G, --generate-key generate a new remailer key\n\
484 -K, --update-keys generate remailer keys if necessary\n\
485 --config=file use alternate configuration file\n"
486 #ifdef WIN32SERVICE
487 "\n\
488 WinNT service:\n\
489 \n\
490 --install-svc install the service\n\
491 --remove-svc remove the service\n\
492 --run-svc run as a service\n"
493 #endif /* WIN32SERVICE */
494 );
495
496 ret = 0;
497 goto end;
498 }
499
500 if (deflt && send == -1)
501 send = MSG_MAIL;
502 if (nym[0] != 0)
503 send = -1;
504 if ((send == MSG_MAIL || send == MSG_POST) && filename == NULL &&
505 header == 1 && isatty(fileno(stdin))) {
506 /* we don't get here if USE_NCURSES is set */
507 printf("Run `%s -h' to view a summary of the command line options.\n\nEnter the message, complete with headers.\n",
508 argv[0]);
509 #ifdef UNIX
510 printf("When done, press ^D.\n\n");
511 #else
512 printf("When done, press ^Z.\n\n");
513 #endif /* else not UNIX */
514 }
515 if (header == 0)
516 buf_nl(msg);
517
518 /* timeskew check */
519 if (REMAIL == 1)
520 mix_check_timeskew();
521
522 if (readmail || redirect_mail || send == MSG_MAIL || send == MSG_POST) {
523 if (filename == NULL || streq(filename, "-"))
524 f = stdin;
525 else {
526 f = fopen(filename, "r");
527 if (f == NULL)
528 fprintf(stderr, "Can't open %s.\n", filename);
529 }
530
531 if (f && buf_read(msg, f) != -1) {
532 if (readmail == 1) {
533 check_get_pass(1, never_ask_for_passphrase);
534 mix_decrypt(msg);
535 } else if (readmail == 2)
536 pool_add(msg, "inf");
537 if (send == MSG_MAIL || send == MSG_POST || redirect_mail) {
538 BUFFER *sendmsg;
539 int numdest = 0;
540
541 sendmsg = buf_new();
542
543 while (buf_getheader(msg, field, content) == 0) {
544 if (bufieq(field, "nym")) {
545 strncpy(nym, content->data, sizeof(nym));
546 } else if (bufieq(field, "chain"))
547 if (strchr(content->data, ';')) {
548 i = strchr(content->data, ';') - (char *)content->data;
549 strncpy(chain, content->data, i);
550 if (strstr(content->data + i, "copies=") != NULL) {
551 sscanf(strstr(content->data + i, "copies=") +
552 sizeof("copies=") - 1, "%d", &numcopies);
553 }
554 } else
555 strncpy(chain, content->data, sizeof(chain));
556 else { /* line goes into message */
557 if (((redirect_mail || send == MSG_MAIL) && bufieq(field, "to"))
558 || (send == MSG_POST && bufieq(field, "newsgroups")))
559 numdest++;
560 if (bufieq(field, "from") && !redirect_mail)
561 fprintf(stderr, "Warning: The message has a From: line.\n");
562 buf_appendheader(sendmsg, field, content);
563 }
564 }
565 buf_nl(sendmsg);
566 buf_rest(sendmsg, msg);
567
568 while (buf_getline(attachments, field) != -1)
569 if (attachfile(sendmsg, field) == -1) {
570 errlog(ERRORMSG, "Can't attach %b!\n", field);
571 ret = 2;
572 goto end;
573 }
574
575 #ifdef USE_PGP
576 if (nym[0] != 0 && strchr(nym, '@') == NULL)
577 strcatn(nym, "@", sizeof(nym));
578 if (sign || encrypt) {
579 BUFFER *pass;
580
581 pass = buf_new();
582 user_pass(pass);
583 if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0) |
584 (nym[0] != 0 && sign ? PGP_SIGN : 0) |
585 PGP_TEXT | PGP_REMAIL, sendmsg, nym,
586 pass, NULL, NYMSECRING) != 0) {
587 fprintf(stderr, "Encryption failed: missing key!");
588 ret = 2;
589 goto end;
590 }
591 buf_free(pass);
592 }
593 if (nym[0] != 0) {
594 #ifdef NYMSUPPORT
595 if (nym_encrypt(sendmsg, nym, send) == 0)
596 send = MSG_MAIL;
597 else
598 #endif /* NYMSUPPORT */
599 fprintf(stderr, "Nym error, sending message anonymously.\n");
600 }
601 #endif /* USE_PGP */
602 if (numdest == 0) {
603 fprintf(stderr, "No destination address given!\n");
604 ret = 2;
605 } else if (numcopies < 0 || numcopies > 10) {
606 fprintf(stderr, "Invalid number of copies!\n");
607 ret = 2;
608 } else {
609 if ( ( redirect_mail ?
610 redirect_message(sendmsg, chain, numcopies, chainlist) :
611 mix_encrypt(send, sendmsg, chain, numcopies, chainlist)
612 ) == -1) {
613 ret = 2;
614 if (chainlist->length)
615 fprintf(stderr, "%s\n", chainlist->data);
616 else
617 fprintf(stderr, "Failed!\n");
618 } else if (verbose) {
619 fprintf(stderr, "Chain: ");
620 buf_write(chainlist, stderr);
621 }
622 }
623
624 buf_free(sendmsg);
625 }
626 if (filename != NULL)
627 fclose(f);
628 } else
629 ret = 2;
630 }
631 if (send == MSG_NULL) {
632 if (msg->length) {
633 while (buf_getheader(msg, field, content) == 0) {
634 if (bufieq(field, "chain"))
635 strncpy(chain, content->data, sizeof(chain));
636 }
637 }
638 if (mix_encrypt(MSG_NULL, NULL, chain, numcopies, chainlist) == -1) {
639 ret = 2;
640 if (chainlist->length)
641 printf("%s\n", chainlist->data);
642 else
643 fprintf(stderr, "Failed!\n");
644 } else if (verbose) {
645 printf("Chain: ");
646 buf_write(chainlist, stdout);
647 }
648 }
649 #ifdef USE_PGP
650 #ifdef NYMSUPPORT
651 if (nym[0] != 0) {
652 char nymserver[LINELEN] = "*";
653 BUFFER *chains;
654
655 chains = buf_new();
656 if (numcopies < 1 || numcopies > 10)
657 numcopies = 1;
658 while (buf_getheader(msg, field, content) != -1) {
659 if (bufieq(field, "chain"))
660 strncpy(chain, content->data, sizeof(chain));
661 else if (bufieq(field, "reply-chain"))
662 buf_appendf(chains, "Chain: %b\n", content);
663 else if (field->length)
664 buf_appendheader(chains, field, content);
665 else
666 buf_nl(chains);
667 }
668 if (strrchr(nym, '@')) {
669 strncpy(nymserver, strrchr(nym, '@'), sizeof(nymserver));
670 *strrchr(nym, '@') = '\0';
671 }
672 if (nym_config(NYM_CREATE, nym, nymserver, pseudonym,
673 chain, numcopies, chains, nymopt) < 0) {
674 ret = 2;
675 fprintf(stderr, "Failed!\n");
676 }
677 user_delpass();
678 buf_free(chains);
679 }
680 #endif /* NYMSUPPORT */
681 #endif /* USE_PGP */
682
683 if (keygen) {
684 check_get_pass(0, never_ask_for_passphrase);
685 keymgt(keygen);
686 }
687 if (sendpool)
688 mix_send();
689 #ifdef USE_SOCK
690 if (pop3)
691 pop3get();
692 #endif /* USE_SOCK */
693 if (maint) {
694 check_get_pass(1, never_ask_for_passphrase);
695 mix_regular(0);
696 }
697
698 clientpool:
699 if ((REMAIL == 0) && (CLIENTAUTOFLUSH == 1)) {
700 SENDPOOLTIME = 0;
701 RATE = 100;
702 mix_send();
703 };
704
705 end:
706 buf_free(field);
707 buf_free(content);
708 buf_free(chainlist);
709 buf_free(msg);
710 buf_free(nymopt);
711 buf_free(pseudonym);
712 buf_free(attachments);
713 buf_free(statssrc);
714
715 if (daemon) {
716 check_get_pass(1, never_ask_for_passphrase);
717 #ifdef UNIX
718 if (! nodetach) {
719 int pid;
720
721 fprintf(stderr, "Detaching.\n");
722 /* Detach as suggested by the Unix Programming FAQ */
723 pid = fork();
724 if (pid > 0)
725 exit(0);
726 if (setsid() < 0) {
727 /* This should never happen. */
728 fprintf(stderr, "setsid() failed.\n");
729 exit(1);
730 };
731 pid = fork();
732 if (pid > 0)
733 exit(0);
734 };
735 if (chdir(MIXDIR) < 0) {
736 if (chdir("/") < 0) {
737 fprintf(stderr, "Cannot chdir to mixdir or /.\n");
738 exit(1);
739 };
740 };
741 if (write_pidfile(PIDFILE)) {
742 fprintf(stderr, "Aborting.\n");
743 exit(1);
744 }
745 if (! nodetach) {
746 freopen ("/dev/null", "r", stdin);
747 freopen ("/dev/null", "w", stdout);
748 freopen ("/dev/null", "w", stderr);
749 }
750 #endif /* UNIX */
751 mix_daemon();
752 #ifdef UNIX
753 /* ifdef this one too, so that we do not need to export it from windows dll */
754 clear_pidfile(PIDFILE);
755 #endif /* UNIX */
756 }
757 mix_exit();
758 return (ret);
759 }
760
761 static char *largopt(char *p, char *opt, char *name, int *error)
762 {
763 if (streq(p, opt)) {
764 fprintf(stderr, "%s: Missing argument for option --%s\n", name, p);
765 *error = 1;
766 } else if (strleft(p, opt) && p[strlen(opt)] == '=') {
767 return (p + strlen(opt) + 1);
768 }
769 return (NULL);
770 }
771
772 static void noarg(char *name, char p)
773 {
774 fprintf(stderr, "%s: Missing argument for option -%c\n", name, p);
775 }
776
777 static int check_get_pass(int force, int never_ask_for_passphrase)
778 /* get a passphrase and check against keys
779 * if force != 0 passphrase must match with some key */
780 {
781 BUFFER *pass, *pass2, *key;
782 int n = 0;
783
784 if (PASSPHRASE[0] == '\0' && isatty(fileno(stdin)) && ! never_ask_for_passphrase) {
785 pass = buf_new();
786 pass2 = buf_new();
787 key = buf_new();
788 buf_sets(pass, PASSPHRASE);
789 while (
790 #ifdef USE_PGP
791 pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL,
792 NULL, NULL, NULL, pass) < 0 &&
793 pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL, NULL,
794 NULL, NULL, NULL, pass) < 0 &&
795 #endif /* USE_PGP */
796 getv2seckey(NULL, key) < 0)
797 {
798 user_delpass();
799 if (n)
800 fprintf(stderr, "re-");
801 user_pass(pass);
802 strncpy(PASSPHRASE, pass->data, LINELEN);
803 PASSPHRASE[LINELEN-1] = 0;
804 if (!force) {
805 if (n && buf_eq(pass, pass2))
806 break;
807 buf_set(pass2, pass);
808 }
809 n=1;
810 }
811 user_delpass();
812 buf_free(pass);
813 buf_free(pass2);
814 buf_free(key);
815
816 strncpy(ENTEREDPASSPHRASE, PASSPHRASE, LINELEN);
817 ENTEREDPASSPHRASE[LINELEN-1] = 0;
818 }
819 return 1;
820 }