/[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 30 - (show annotations) (download)
Tue Dec 11 20:59:26 2001 UTC (11 years, 5 months ago) by rabbi
File MIME type: text/plain
File size: 15421 byte(s)
Changes for WIN32 Service support. service.c is totally re-written,
service.h is removed. main.c is now cleaner.

TODO: better solution to the Win32/Unix directory seperation issue. Sring
operations on every path is a lot of extra work. Why not fopen() ?
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.3 2001/12/11 20:59:26 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 case 'a':
261 if (i < argc - 1)
262 buf_appendf(attachments, "%s\n", argv[++i]);
263 else {
264 noarg(argv[0], *p);
265 error = 1;
266 }
267 case 'm':
268 send = MSG_MAIL;
269 break;
270 default:
271 fprintf(stderr, "%s: Invalid option -%c\n", argv[0], *p);
272 error = 1;
273 break;
274 }
275 }
276 }
277 } else {
278 if (strchr(argv[i], '@')) {
279 header = 0;
280 buf_appendf(msg, "To: %s\n", argv[i]);
281 } else {
282 if (filename == NULL)
283 filename = argv[i];
284 else {
285 fprintf(stderr, "%s: Error in command line: %s\n", argv[0], argv[i]);
286 error = 1;
287 }
288 }
289 }
290 }
291
292 if (error) {
293 ret = 1;
294 goto end;
295 }
296 if (type_list) {
297 if (file_to_out(TYPE2LIST) < 0) {
298 fprintf(stderr, "File %s not found.\n", TYPE2LIST);
299 }
300 goto end;
301 }
302 if (help || (isatty(fileno(stdin)) && isatty(fileno(stdout))))
303 fprintf(stderr, "Mixmaster %s - %s\n", VERSION, COPYRIGHT);
304
305 if (help) {
306 printf("Usage: %s [options] [user@host] [filename]\n\n", argv[0]);
307 printf("Options:\n\
308 \n\
309 -h, --help summary of command line options\n\
310 -T, --type-list list available remailers\n\
311 -t, --to=user@host the recipient's address(es)\n\
312 -g, --post-to=newsgroup newsgroup(s) to post to\n\
313 -p, --post input is a Usenet article\n\
314 -m, --mail input is a mail message\n\
315 -s, --subject=subject message subject\n\
316 --header='header line' arbitrary message headers\n\
317 -a, --attachment=file attach a file\n"
318 #ifdef USE_PGP
319 "-n, --nym=yournym use pseudonym to send the message\n\
320 --encrypt encrypt the message using the PGP format\n\
321 --sign sign the message using the PGP format\n"
322 #endif
323 "-l, --chain=mix1,mix2,mix3,... specify a remailer chain\n\
324 -c, --copies=num send num copies to increase reliability\n\
325 -d, --dummy generate a dummy message\n\
326 -S, --send send the message(s) in the pool\n"
327 #ifdef USE_PGP
328 " --nym-config=yournym generate a new pseudonym\n\
329 --latency=hours reply chain latency\n\
330 --reply-chain=rem1,rem2,... reply chain for the pseudonym\n"
331 #endif
332 "-v, --verbose output informational messages\n\
333 -f [file] read a mail folder\n"
334 #ifndef USE_NCURSES
335 "\n-fr, -ff, -fg [file] send reply/followup/group reply to a message\n"
336 #endif
337 "\nThe input file is expected to contain mail headers if no address is\n\
338 specified in the command line.\n\
339 \n\
340 Remailer:\n\
341 \n\
342 -R, --read-mail read remailer message from stdin\n\
343 -M, --remailer process the remailer pool\n\
344 -D, --daemon remailer as background process\n"
345 #ifdef USE_SOCK
346 "-S, --send force sending messages from the pool\n"
347 #endif
348 "-P, --pop-mail force getting messages from POP3 servers\n\
349 -G, --generate-key generate a new remailer key\n\
350 -K, --update-keys generate remailer keys if necessary\n"
351 #ifdef WIN32SERVICE
352 "\n\
353 WinNT service:\n\
354 \n\
355 --install to install the service\n\
356 --remove to remove the service\n"
357 #endif
358 );
359
360 ret = 0;
361 goto end;
362 }
363 if (deflt && send == -1)
364 send = MSG_MAIL;
365 if (nym[0] != 0)
366 send = -1;
367 if ((send == MSG_MAIL || send == MSG_POST) && filename == NULL &&
368 header == 1 && isatty(fileno(stdin))) {
369 /* we don't get here if USE_NCURSES is set */
370 printf("Run `%s -h' to view a summary of the command line options.\n\nEnter the message, complete with headers.\n",
371 argv[0]);
372 #ifdef UNIX
373 printf("When done, press ^D.\n\n");
374 #else
375 printf("When done, press ^Z.\n\n");
376 #endif
377 }
378 if (header == 0)
379 buf_nl(msg);
380
381 if (readmail || send == MSG_MAIL || send == MSG_POST) {
382 if (filename == NULL || streq(filename, "-"))
383 f = stdin;
384 else {
385 f = fopen(filename, "r");
386 if (f == NULL)
387 fprintf(stderr, "Can't open %s.\n", filename);
388 }
389
390 if (f && buf_read(msg, f) != -1) {
391 if (readmail)
392 mix_decrypt(msg);
393 if (send == MSG_MAIL || send == MSG_POST) {
394 BUFFER *sendmsg;
395 int numdest = 0;
396
397 sendmsg = buf_new();
398
399 while (buf_getheader(msg, field, content) == 0) {
400 if (bufieq(field, "nym")) {
401 strncpy(nym, content->data, sizeof(nym));
402 } else if (bufieq(field, "chain"))
403 if (strchr(content->data, ';')) {
404 i = strchr(content->data, ';') - (char *)content->data;
405 strncpy(chain, content->data, i);
406 if (strstr(content->data + i, "copies=") != NULL) {
407 sscanf(strstr(content->data + i, "copies=") +
408 sizeof("copies=") - 1, "%d", &numcopies);
409 }
410 } else
411 strncpy(chain, content->data, sizeof(chain));
412 else { /* line goes into message */
413 if ((send == MSG_MAIL && bufieq(field, "to"))
414 || (send == MSG_POST && bufieq(field, "newsgroups")))
415 numdest++;
416 if (bufieq(field, "from"))
417 fprintf(stderr, "Warning: The message has a From: line.\n");
418 buf_appendheader(sendmsg, field, content);
419 }
420 }
421 buf_nl(sendmsg);
422 buf_rest(sendmsg, msg);
423
424 while (buf_getline(attachments, field) != -1)
425 if (attachfile(sendmsg, field) == -1) {
426 errlog(ERRORMSG, "Can't attach %b!\n", field);
427 ret = 2;
428 goto end;
429 }
430
431 #ifdef USE_PGP
432 if (nym[0] != 0 && strchr(nym, '@') == NULL)
433 strcatn(nym, "@", sizeof(nym));
434 if (sign || encrypt) {
435 BUFFER *pass;
436
437 pass = buf_new();
438 user_pass(pass);
439 if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0) |
440 (nym[0] != 0 && sign ? PGP_SIGN : 0) |
441 PGP_TEXT | PGP_REMAIL, sendmsg, nym,
442 pass, NULL, NYMSECRING) != 0) {
443 fprintf(stderr, "Encryption failed: missing key!");
444 ret = 2;
445 goto end;
446 }
447 buf_free(pass);
448 }
449 if (nym[0] != 0) {
450 if (nym_encrypt(sendmsg, nym, send) == 0)
451 send = MSG_MAIL;
452 else
453 fprintf(stderr, "Nym error, sending message anonymously.\n");
454 }
455 #endif
456 if (numdest == 0) {
457 fprintf(stderr, "No destination address given!\n");
458 ret = 2;
459 } else if (numcopies < 0 || numcopies > 10) {
460 fprintf(stderr, "Invalid number of copies!\n");
461 ret = 2;
462 } else {
463 if (mix_encrypt(send, sendmsg, chain, numcopies,
464 chainlist) == -1) {
465 ret = 2;
466 if (chainlist->length)
467 fprintf(stderr, "%s\n", chainlist->data);
468 else
469 fprintf(stderr, "Failed!\n");
470 } else if (verbose) {
471 fprintf(stderr, "Chain: ");
472 buf_write(chainlist, stderr);
473 }
474 }
475
476 buf_free(sendmsg);
477 }
478 if (filename != NULL)
479 fclose(f);
480 } else
481 ret = 2;
482 }
483 if (send == MSG_NULL) {
484 if (msg->length) {
485 while (buf_getheader(msg, field, content) == 0) {
486 if (bufieq(field, "chain"))
487 strncpy(chain, content->data, sizeof(chain));
488 }
489 }
490 if (mix_encrypt(MSG_NULL, NULL, chain, numcopies, 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 #ifdef USE_PGP
502 if (nym[0] != 0) {
503 char nymserver[LINELEN] = "*";
504 BUFFER *chains;
505
506 chains = buf_new();
507 if (numcopies < 1 || numcopies > 10)
508 numcopies = 1;
509 while (buf_getheader(msg, field, content) != -1) {
510 if (bufieq(field, "chain"))
511 strncpy(chain, content->data, sizeof(chain));
512 else if (bufieq(field, "reply-chain"))
513 buf_appendf(chains, "Chain: %b\n", content);
514 else if (field->length)
515 buf_appendheader(chains, field, content);
516 else
517 buf_nl(chains);
518 }
519 if (strchr(nym, '@')) {
520 strncpy(nymserver, strchr(nym, '@'), sizeof(nymserver));
521 *strchr(nym, '@') = '\0';
522 }
523 if (nym_config(NYM_CREATE, nym, nymserver, pseudonym,
524 chain, numcopies, chains, nymopt) < 0) {
525 ret = 2;
526 fprintf(stderr, "Failed!\n");
527 }
528 user_delpass();
529 buf_free(chains);
530 }
531 #endif
532
533 if (keygen)
534 keymgt(keygen);
535 if (sendpool)
536 mix_send();
537 #ifdef USE_SOCK
538 if (pop3)
539 pop3get();
540 #endif
541 if (maint)
542 mix_regular(0);
543
544 end:
545 buf_free(field);
546 buf_free(content);
547 buf_free(chainlist);
548 buf_free(msg);
549 buf_free(nymopt);
550 buf_free(pseudonym);
551 buf_free(attachments);
552
553 if (daemon) {
554 #ifdef UNIX
555 int pid;
556
557 fprintf(stderr, "Detaching.\n");
558 pid = fork();
559 if (pid > 0)
560 exit(0);
561 #endif
562 mix_daemon();
563 }
564 mix_exit();
565 return (ret);
566 }
567
568 static char *largopt(char *p, char *opt, char *name, int *error)
569 {
570 if (streq(p, opt)) {
571 fprintf(stderr, "%s: Missing argument for option --%s\n", name, p);
572 *error = 1;
573 } else if (strleft(p, opt) && p[strlen(opt)] == '=') {
574 return (p + strlen(opt) + 1);
575 }
576 return (NULL);
577 }
578
579 static void noarg(char *name, char p)
580 {
581 fprintf(stderr, "%s: Missing argument for option -%c\n", name, p);
582 }

  ViewVC Help
Powered by ViewVC 1.1.5