/[pkg-mixmaster]/branches/mixmaster_2_9_STABLE/Mix/Src/main.c
ViewVC logotype

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 652 - (show annotations) (download)
Fri Nov 7 07:44:16 2003 UTC (9 years, 6 months ago) by weasel
File MIME type: text/plain
File size: 17438 byte(s)
Add source revision to version shown in the menu and in non-curses interface
1 /* Mixmaster version 2.9 -- (C) 1999 - 2002 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$ */
10
11
12 #include "mix3.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <stdlib.h>
17 #ifdef POSIX
18 #include <unistd.h>
19 #else /* end of POSIX */
20 #include <io.h>
21 #endif /* else if not POSIX */
22
23 static char *largopt(char *p, char *opt, char *name, int *error);
24 static void noarg(char *name, char p);
25
26 /** main *****************************************************************/
27
28 /* Returns:
29 0 successful operation
30 1 command line error
31 2 client error condition */
32
33 #ifdef WIN32SERVICE
34 int mix_main(int argc, char *argv[])
35 #else
36 int main(int argc, char *argv[])
37 #endif /* WIN32SERVICE */
38 {
39 int error = 0, deflt = 1, help = 0, readmail = 0, send = -1, sendpool = 0,
40 header = 1, maint = 0, keygen = 0, verbose = 2, sign = 0, encrypt = 0;
41 int daemon = 0, type_list = 0, nodetach = 0;
42
43 #ifdef USE_SOCK
44 int pop3 = 0;
45
46 #endif /* USE_SOCK */
47 char *filename = NULL;
48 int i;
49 int ret = 0;
50 char *p, *q;
51 char chain[1024] = "";
52 char nym[LINELEN] = "";
53 BUFFER *nymopt, *pseudonym, *attachments;
54 int numcopies = 0; /* default value set in mix.cfg */
55 BUFFER *msg, *chainlist, *field, *content;
56 FILE *f;
57
58 mix_init(NULL);
59
60 msg = buf_new();
61 chainlist = buf_new();
62 nymopt = buf_new();
63 pseudonym = buf_new();
64 attachments = buf_new();
65 field = buf_new();
66 content = buf_new();
67
68 #ifdef USE_NCURSES
69 if (argc == 1) {
70 if (isatty(fileno(stdin)))
71 menu_main();
72 else
73 menu_folder(0, NULL);
74 goto end;
75 }
76 #endif /* USE_NCURSES */
77 if (argc > 1 && strleft(argv[1], "-f")) {
78 menu_folder(strlen(argv[1]) > 2 ? argv[1][2] : 0,
79 argc < 3 ? NULL : argv[2]);
80 goto end;
81 }
82 for (i = 1; i < argc; i++) {
83 p = argv[i];
84 if (p[0] == '-' && p[1] != '\0') {
85 if (p[1] == '-') {
86 p += 2;
87 if (strieq(p, "help"))
88 help = 1, deflt = 0;
89 else if (streq(p, "verbose"))
90 verbose = 1;
91 else if (streq(p, "type-list"))
92 type_list = 1;
93 else if (streq(p, "dummy"))
94 send = MSG_NULL, deflt = 0;
95 else if (streq(p, "remailer"))
96 maint = 1, deflt = 0;
97 else if (streq(p, "generate-key"))
98 keygen = 2, deflt = 0;
99 else if (streq(p, "update-keys"))
100 keygen = 1, deflt = 0;
101 else if (streq(p, "send"))
102 sendpool = 1, deflt = 0;
103 else if (streq(p, "read-mail"))
104 readmail = 1, deflt = 0;
105 else if (streq(p, "store-mail"))
106 readmail = 2, deflt = 0;
107 #ifdef USE_SOCK
108 else if (streq(p, "pop-mail"))
109 pop3 = 1, deflt = 0;
110 #endif /* USE_SOCK */
111 else if (streq(p, "daemon"))
112 daemon = 1, deflt = 0;
113 else if (streq(p, "no-detach"))
114 nodetach = 1;
115 else if (streq(p, "post"))
116 send = MSG_POST;
117 else if (streq(p, "mail"))
118 send = MSG_MAIL;
119 else if (streq(p, "sign"))
120 sign = 1;
121 else if (streq(p, "encrypt"))
122 encrypt = 1;
123 else if ((q = largopt(p, "to", argv[0], &error)) != NULL) {
124 header = 0;
125 buf_appendf(msg, "To: %s\n", q);
126 } else if ((q = largopt(p, "post-to", argv[0], &error)) != NULL) {
127 send = MSG_POST, header = 0;
128 buf_appendf(msg, "Newsgroups: %s\n", q);
129 } else if ((q = largopt(p, "subject", argv[0], &error)) != NULL) {
130 buf_appendf(msg, "Subject: %s\n", q);
131 } else if ((q = largopt(p, "header", argv[0], &error)) != NULL) {
132 buf_appendf(msg, "%s\n", q);
133 } else if ((q = largopt(p, "chain", argv[0], &error)) != NULL) {
134 buf_appendf(msg, "Chain: %s\n", q);
135 }
136 #ifdef USE_PGP
137 else if ((q = largopt(p, "reply-chain", argv[0], &error)) != NULL) {
138 buf_appendf(msg, "Reply-Chain: %s\n", q);
139 } else if ((q = largopt(p, "latency", argv[0], &error)) != NULL) {
140 buf_appendf(msg, "Latency: %s\n", q);
141 } else if ((q = largopt(p, "attachment", argv[0], &error)) != NULL) {
142 buf_appendf(attachments, "%s\n", q);
143 } else if ((q = largopt(p, "nym-config", argv[0], &error)) != NULL) {
144 deflt = 0;
145 strncpy(nym, q, sizeof(nym));
146 if (i > argc && strileft(argv[i + 1], "name="))
147 buf_sets(pseudonym, argv[++i] + 5);
148 else if (i > argc && strileft(argv[i + 1], "opt="))
149 buf_appends(nymopt, argv[++i] + 5);
150 } else if ((q = largopt(p, "nym", argv[0], &error)) != NULL) {
151 buf_appendf(msg, "Nym: %s\n", q);
152 }
153 #endif /* USE_PGP */
154 else if ((q = largopt(p, "copies", argv[0], &error)) != NULL) {
155 sscanf(q, "%d", &numcopies);
156 } else if ((q = largopt(p, "config", argv[0], &error)) != NULL) {
157 strncpy(MIXCONF, q, PATHMAX);
158 MIXCONF[PATHMAX-1] = 0;
159 mix_config(); /* configuration file changed - reread it */
160 } else if (error == 0 && mix_configline(p) == 0) {
161 fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]);
162 error = 1;
163 }
164 } else {
165 while (*++p) {
166 switch (*p) {
167 case 'd':
168 send = MSG_NULL, deflt = 0;
169 break;
170 case 'R':
171 readmail = 1, deflt = 0;
172 break;
173 case 'I':
174 readmail = 2, deflt = 0;
175 break;
176 case 'S':
177 sendpool = 1, deflt = 0;
178 break;
179 case 'M':
180 maint = 1, deflt = 0;
181 break;
182 #ifdef USE_SOCK
183 case 'P':
184 pop3 = 1, deflt = 0;
185 break;
186 #endif /* USE_SOCK */
187 case 'D':
188 daemon = 1, deflt = 0;
189 break;
190 case 'G':
191 keygen = 2, deflt = 0;
192 break;
193 case 'K':
194 keygen = 1, deflt = 0;
195 break;
196 case 'L': /* backwards compatibility */
197 break;
198 case 'v':
199 verbose = 1;
200 break;
201 case 'h':
202 help = 1, deflt = 0;
203 break;
204 case 'T':
205 type_list = 1;
206 break;
207 case 't':
208 if (*(p + 1) == 'o')
209 p++;
210 header = 0;
211 if (i < argc - 1)
212 buf_appendf(msg, "To: %s\n", argv[++i]);
213 else {
214 fprintf(stderr, "%s: Missing argument for option -to\n",
215 argv[0]);
216 error = 1;
217 }
218 break;
219 case 's':
220 if (i < argc - 1)
221 buf_appendf(msg, "Subject: %s\n", argv[++i]);
222 else {
223 noarg(argv[0], *p);
224 error = 1;
225 }
226 break;
227 case 'l':
228 if (i < argc - 1)
229 buf_appendf(msg, "Chain: %s\n", argv[++i]);
230 else {
231 noarg(argv[0], *p);
232 error = 1;
233 }
234 break;
235 case 'r':
236 if (i < argc - 1)
237 buf_appendf(msg, "Reply-Chain: %s\n", argv[++i]);
238 else {
239 noarg(argv[0], *p);
240 error = 1;
241 }
242 break;
243 #ifdef USE_PGP
244 case 'n':
245 if (i < argc - 1)
246 buf_appendf(msg, "Nym: %s\n", argv[++i]);
247 else {
248 noarg(argv[0], *p);
249 error = 1;
250 }
251 break;
252 #endif /* USE_PGP */
253 case 'c':
254 if (i < argc - 1)
255 sscanf(argv[++i], "%d", &numcopies);
256 else {
257 noarg(argv[0], *p);
258 error = 1;
259 }
260 break;
261 case 'p':
262 send = MSG_POST;
263 break;
264 case 'g':
265 if (i < argc - 1) {
266 send = MSG_POST, header = 0;
267 buf_appendf(msg, "Newsgroups: %s\n", argv[++i]);
268 } else {
269 noarg(argv[0], *p);
270 error = 1;
271 }
272 break;
273 case 'a':
274 if (i < argc - 1)
275 buf_appendf(attachments, "%s\n", argv[++i]);
276 else {
277 noarg(argv[0], *p);
278 error = 1;
279 }
280 break;
281 case 'm':
282 send = MSG_MAIL;
283 break;
284 default:
285 fprintf(stderr, "%s: Invalid option -%c\n", argv[0], *p);
286 error = 1;
287 break;
288 }
289 }
290 }
291 } else {
292 if (strchr(argv[i], '@')) {
293 header = 0;
294 buf_appendf(msg, "To: %s\n", argv[i]);
295 } else {
296 if (filename == NULL)
297 filename = argv[i];
298 else {
299 fprintf(stderr, "%s: Error in command line: %s\n", argv[0], argv[i]);
300 error = 1;
301 }
302 }
303 }
304 }
305
306 if (error) {
307 ret = 1;
308 goto end;
309 }
310 if (type_list) {
311 BUFFER *type2list;
312 type2list = buf_new();
313 if (prepare_type2list(type2list) < 0) {
314 fprintf(stderr, "Cannot print type2.list.\n");
315 ret = 2;
316 } else {
317 printf("%s", type2list->data);
318 };
319 buf_free(type2list);
320 goto end;
321 }
322 if (help || (isatty(fileno(stdin)) && isatty(fileno(stdout))))
323 fprintf(stderr, "Mixmaster %s (%s) - %s\n", VERSION, SOURCE_REVISION, COPYRIGHT);
324
325 if (help) {
326 printf("Usage: %s [options] [user@host] [filename]\n\n", argv[0]);
327 printf("Options:\n\
328 \n\
329 -h, --help summary of command line options\n\
330 -T, --type-list list available remailers\n\
331 -t, --to=user@host the recipient's address(es)\n\
332 -g, --post-to=newsgroup newsgroup(s) to post to\n\
333 -p, --post input is a Usenet article\n\
334 -m, --mail input is a mail message\n\
335 -s, --subject=subject message subject\n\
336 --header='header line' arbitrary message headers\n\
337 -a, --attachment=file attach a file\n"
338 #ifdef USE_PGP
339 "-n, --nym=yournym use pseudonym to send the message\n\
340 --encrypt encrypt the message using the PGP format\n\
341 --sign sign the message using the PGP format\n"
342 #endif /* USE_PGP */
343 "-l, --chain=mix1,mix2,mix3,... specify a remailer chain\n\
344 -c, --copies=num send num copies to increase reliability\n\
345 -d, --dummy generate a dummy message\n\
346 -S, --send send the message(s) in the pool\n"
347 #ifdef USE_PGP
348 " --nym-config=yournym generate a new pseudonym\n\
349 --latency=hours reply chain latency\n\
350 --reply-chain=rem1,rem2,... reply chain for the pseudonym\n"
351 #endif /* USE_PGP */
352 "-v, --verbose output informational messages\n\
353 -f [file] read a mail folder\n"
354 #ifndef USE_NCURSES
355 "\n-fr, -ff, -fg [file] send reply/followup/group reply to a message\n"
356 #endif /* USE_NCURSES */
357 "\nThe input file is expected to contain mail headers if no address is\n\
358 specified in the command line.\n\
359 \n\
360 Remailer:\n\
361 \n\
362 -R, --read-mail read remailer message from stdin\n\
363 -I, --store-mail read remailer msg from stdin, do not decrypt\n\
364 -M, --remailer process the remailer pool\n\
365 -D, --daemon remailer as background process\n\
366 --no-detach do not detach from terminal as daemon\n"
367 #ifdef USE_SOCK
368 "-S, --send force sending messages from the pool\n"
369 #endif /* USE_SOCK */
370 "-P, --pop-mail force getting messages from POP3 servers\n\
371 -G, --generate-key generate a new remailer key\n\
372 -K, --update-keys generate remailer keys if necessary\n\
373 --config=file use alternate configuration file\n"
374 #ifdef WIN32SERVICE
375 "\n\
376 WinNT service:\n\
377 \n\
378 --install-svc install the service\n\
379 --remove-svc remove the service\n\
380 --run-svc run as a service\n"
381 #endif /* WIN32SERVICE */
382 );
383
384 ret = 0;
385 goto end;
386 }
387 if (deflt && send == -1)
388 send = MSG_MAIL;
389 if (nym[0] != 0)
390 send = -1;
391 if ((send == MSG_MAIL || send == MSG_POST) && filename == NULL &&
392 header == 1 && isatty(fileno(stdin))) {
393 /* we don't get here if USE_NCURSES is set */
394 printf("Run `%s -h' to view a summary of the command line options.\n\nEnter the message, complete with headers.\n",
395 argv[0]);
396 #ifdef UNIX
397 printf("When done, press ^D.\n\n");
398 #else
399 printf("When done, press ^Z.\n\n");
400 #endif /* else not UNIX */
401 }
402 if (header == 0)
403 buf_nl(msg);
404
405 if (readmail || send == MSG_MAIL || send == MSG_POST) {
406 if (filename == NULL || streq(filename, "-"))
407 f = stdin;
408 else {
409 f = fopen(filename, "r");
410 if (f == NULL)
411 fprintf(stderr, "Can't open %s.\n", filename);
412 }
413
414 if (f && buf_read(msg, f) != -1) {
415 if (readmail == 1)
416 mix_decrypt(msg);
417 else if (readmail == 2)
418 pool_add(msg, "inf");
419 if (send == MSG_MAIL || send == MSG_POST) {
420 BUFFER *sendmsg;
421 int numdest = 0;
422
423 sendmsg = buf_new();
424
425 while (buf_getheader(msg, field, content) == 0) {
426 if (bufieq(field, "nym")) {
427 strncpy(nym, content->data, sizeof(nym));
428 } else if (bufieq(field, "chain"))
429 if (strchr(content->data, ';')) {
430 i = strchr(content->data, ';') - (char *)content->data;
431 strncpy(chain, content->data, i);
432 if (strstr(content->data + i, "copies=") != NULL) {
433 sscanf(strstr(content->data + i, "copies=") +
434 sizeof("copies=") - 1, "%d", &numcopies);
435 }
436 } else
437 strncpy(chain, content->data, sizeof(chain));
438 else { /* line goes into message */
439 if ((send == MSG_MAIL && bufieq(field, "to"))
440 || (send == MSG_POST && bufieq(field, "newsgroups")))
441 numdest++;
442 if (bufieq(field, "from"))
443 fprintf(stderr, "Warning: The message has a From: line.\n");
444 buf_appendheader(sendmsg, field, content);
445 }
446 }
447 buf_nl(sendmsg);
448 buf_rest(sendmsg, msg);
449
450 while (buf_getline(attachments, field) != -1)
451 if (attachfile(sendmsg, field) == -1) {
452 errlog(ERRORMSG, "Can't attach %b!\n", field);
453 ret = 2;
454 goto end;
455 }
456
457 #ifdef USE_PGP
458 if (nym[0] != 0 && strchr(nym, '@') == NULL)
459 strcatn(nym, "@", sizeof(nym));
460 if (sign || encrypt) {
461 BUFFER *pass;
462
463 pass = buf_new();
464 user_pass(pass);
465 if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0) |
466 (nym[0] != 0 && sign ? PGP_SIGN : 0) |
467 PGP_TEXT | PGP_REMAIL, sendmsg, nym,
468 pass, NULL, NYMSECRING) != 0) {
469 fprintf(stderr, "Encryption failed: missing key!");
470 ret = 2;
471 goto end;
472 }
473 buf_free(pass);
474 }
475 if (nym[0] != 0) {
476 if (nym_encrypt(sendmsg, nym, send) == 0)
477 send = MSG_MAIL;
478 else
479 fprintf(stderr, "Nym error, sending message anonymously.\n");
480 }
481 #endif /* USE_PGP */
482 if (numdest == 0) {
483 fprintf(stderr, "No destination address given!\n");
484 ret = 2;
485 } else if (numcopies < 0 || numcopies > 10) {
486 fprintf(stderr, "Invalid number of copies!\n");
487 ret = 2;
488 } else {
489 if (mix_encrypt(send, sendmsg, chain, numcopies,
490 chainlist) == -1) {
491 ret = 2;
492 if (chainlist->length)
493 fprintf(stderr, "%s\n", chainlist->data);
494 else
495 fprintf(stderr, "Failed!\n");
496 } else if (verbose) {
497 fprintf(stderr, "Chain: ");
498 buf_write(chainlist, stderr);
499 }
500 }
501
502 buf_free(sendmsg);
503 }
504 if (filename != NULL)
505 fclose(f);
506 } else
507 ret = 2;
508 }
509 if (send == MSG_NULL) {
510 if (msg->length) {
511 while (buf_getheader(msg, field, content) == 0) {
512 if (bufieq(field, "chain"))
513 strncpy(chain, content->data, sizeof(chain));
514 }
515 }
516 if (mix_encrypt(MSG_NULL, NULL, chain, numcopies, chainlist) == -1) {
517 ret = 2;
518 if (chainlist->length)
519 fprintf(stderr, "%s\n", chainlist->data);
520 else
521 fprintf(stderr, "Failed!\n");
522 } else if (verbose) {
523 fprintf(stderr, "Chain: ");
524 buf_write(chainlist, stderr);
525 }
526 }
527 #ifdef USE_PGP
528 if (nym[0] != 0) {
529 char nymserver[LINELEN] = "*";
530 BUFFER *chains;
531
532 chains = buf_new();
533 if (numcopies < 1 || numcopies > 10)
534 numcopies = 1;
535 while (buf_getheader(msg, field, content) != -1) {
536 if (bufieq(field, "chain"))
537 strncpy(chain, content->data, sizeof(chain));
538 else if (bufieq(field, "reply-chain"))
539 buf_appendf(chains, "Chain: %b\n", content);
540 else if (field->length)
541 buf_appendheader(chains, field, content);
542 else
543 buf_nl(chains);
544 }
545 if (strrchr(nym, '@')) {
546 strncpy(nymserver, strrchr(nym, '@'), sizeof(nymserver));
547 *strrchr(nym, '@') = '\0';
548 }
549 if (nym_config(NYM_CREATE, nym, nymserver, pseudonym,
550 chain, numcopies, chains, nymopt) < 0) {
551 ret = 2;
552 fprintf(stderr, "Failed!\n");
553 }
554 user_delpass();
555 buf_free(chains);
556 }
557 #endif /* USE_PGP */
558
559 if (keygen)
560 keymgt(keygen);
561 if (sendpool)
562 mix_send();
563 #ifdef USE_SOCK
564 if (pop3)
565 pop3get();
566 #endif /* USE_SOCK */
567 if (maint)
568 mix_regular(0);
569 if (REMAIL == 0)
570 mix_regular(0); /* check client pool */
571
572 end:
573 buf_free(field);
574 buf_free(content);
575 buf_free(chainlist);
576 buf_free(msg);
577 buf_free(nymopt);
578 buf_free(pseudonym);
579 buf_free(attachments);
580
581 if (daemon) {
582 #ifdef UNIX
583 if (! nodetach) {
584 int pid;
585
586 fprintf(stderr, "Detaching.\n");
587 /* Detach as suggested by the Unix Programming FAQ */
588 pid = fork();
589 if (pid > 0)
590 exit(0);
591 if (setsid() < 0) {
592 /* This should never happen. */
593 fprintf(stderr, "setsid() failed.\n");
594 exit(1);
595 };
596 pid = fork();
597 if (pid > 0)
598 exit(0);
599 };
600 if (chdir(MIXDIR) < 0) {
601 if (chdir("/") < 0) {
602 fprintf(stderr, "Cannot chdir to mixdir or /.\n");
603 exit(1);
604 };
605 };
606 if (write_pidfile(PIDFILE)) {
607 fprintf(stderr, "Aborting.\n");
608 exit(1);
609 }
610 if (! nodetach) {
611 freopen ("/dev/null", "r", stdin);
612 freopen ("/dev/null", "w", stdout);
613 freopen ("/dev/null", "w", stderr);
614 }
615 #endif /* UNIX */
616 mix_daemon();
617 #ifdef UNIX
618 /* ifdef this one to, so that we do not need to export it from windows dll */
619 clear_pidfile(PIDFILE);
620 #endif /* UNIX */
621 }
622 mix_exit();
623 return (ret);
624 }
625
626 static char *largopt(char *p, char *opt, char *name, int *error)
627 {
628 if (streq(p, opt)) {
629 fprintf(stderr, "%s: Missing argument for option --%s\n", name, p);
630 *error = 1;
631 } else if (strleft(p, opt) && p[strlen(opt)] == '=') {
632 return (p + strlen(opt) + 1);
633 }
634 return (NULL);
635 }
636
637 static void noarg(char *name, char p)
638 {
639 fprintf(stderr, "%s: Missing argument for option -%c\n", name, p);
640 }

Properties

Name Value
svn:eol-style native
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5