/[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 65 - (show annotations) (download)
Tue Jan 29 02:47:12 2002 UTC (11 years, 3 months ago) by rabbi
File MIME type: text/plain
File size: 15493 byte(s)
Fixes argument handling bug pointed out by Antonomasia.

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

  ViewVC Help
Powered by ViewVC 1.1.5