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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5