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

  ViewVC Help
Powered by ViewVC 1.1.5