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

  ViewVC Help
Powered by ViewVC 1.1.5