Sieve: "stdin" working mode.
* sieve/sieve.c: New working mode: if `-f -' is given, treat stdin as an RFC2822 message, apply the script to it and exit with 1 if the message gets deleted, 0 if it is not and EX_SOFTWARE on software errors. In traditional mode, exit with standard sysexit codes. * testsuite/sieve/i-numeric.exp: Reflect changes in sieve. * NEWS: Update.
Showing
4 changed files
with
173 additions
and
104 deletions
1 | 2008-10-23 Sergey Poznyakoff <gray@gnu.org.ua> | ||
2 | |||
3 | * sieve/sieve.c: New working mode: if `-f -' is given, treat | ||
4 | stdin as an RFC2822 message, apply the script to it and exit with | ||
5 | 1 if the message gets deleted, 0 if it is not and EX_SOFTWARE on | ||
6 | software errors. | ||
7 | In traditional mode, exit with standard sysexit codes. | ||
8 | * testsuite/sieve/i-numeric.exp: Reflect changes in sieve. | ||
9 | * NEWS: Update. | ||
10 | |||
1 | 2008-10-19 Sergey Poznyakoff <gray@gnu.org.ua> | 11 | 2008-10-19 Sergey Poznyakoff <gray@gnu.org.ua> |
2 | 12 | ||
3 | * auth/sql.c (decode_tuple): Use new tuple parsing mode, unless | 13 | * auth/sql.c (decode_tuple): Use new tuple parsing mode, unless | ... | ... |
1 | GNU mailutils NEWS -- history of user-visible changes. 2008-10-16 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2008-10-23 |
2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, | 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, |
3 | 2008 Free Software Foundation, Inc. | 3 | 2008 Free Software Foundation, Inc. |
4 | See the end of file for copying conditions. | 4 | See the end of file for copying conditions. |
... | @@ -474,6 +474,14 @@ from the available data. | ... | @@ -474,6 +474,14 @@ from the available data. |
474 | New options `--bulletin-db' and `--bulletin-source' implement bulletin | 474 | New options `--bulletin-db' and `--bulletin-source' implement bulletin |
475 | facility. | 475 | facility. |
476 | 476 | ||
477 | * The `sieve' utility. | ||
478 | |||
479 | Exit codes conform to sysexits.h. | ||
480 | |||
481 | New working mode: if `-f -' is given, treat stdin as an RFC2822 | ||
482 | message, apply the script to it and exit with 1 if the message gets | ||
483 | deleted, 0 if it is not and EX_SOFTWARE on software errors. | ||
484 | |||
477 | * MH changes | 485 | * MH changes |
478 | 486 | ||
479 | ** sortm uses stable sort algorithm. | 487 | ** sortm uses stable sort algorithm. | ... | ... |
... | @@ -30,6 +30,7 @@ | ... | @@ -30,6 +30,7 @@ |
30 | #include <string.h> | 30 | #include <string.h> |
31 | #include <unistd.h> | 31 | #include <unistd.h> |
32 | #include <syslog.h> | 32 | #include <syslog.h> |
33 | #include <sysexits.h> | ||
33 | 34 | ||
34 | #include <mu_asprintf.h> | 35 | #include <mu_asprintf.h> |
35 | #include <mailutils/argcv.h> | 36 | #include <mailutils/argcv.h> |
... | @@ -366,6 +367,146 @@ _sieve_action_log (void *unused, | ... | @@ -366,6 +367,146 @@ _sieve_action_log (void *unused, |
366 | mu_debug_set_locus (debug, NULL, 0); | 367 | mu_debug_set_locus (debug, NULL, 0); |
367 | } | 368 | } |
368 | 369 | ||
370 | static int | ||
371 | sieve_message (mu_sieve_machine_t mach) | ||
372 | { | ||
373 | int rc; | ||
374 | mu_stream_t instr; | ||
375 | mu_message_t msg; | ||
376 | mu_attribute_t attr; | ||
377 | |||
378 | rc = mu_stdio_stream_create (&instr, stdin, 0); | ||
379 | if (rc) | ||
380 | { | ||
381 | mu_error (_("Cannot create stream: %s"), mu_strerror (rc)); | ||
382 | return EX_SOFTWARE; | ||
383 | } | ||
384 | rc = mu_stream_open (instr); | ||
385 | if (rc) | ||
386 | { | ||
387 | mu_error (_("Cannot open stream: %s"), mu_strerror (rc)); | ||
388 | return EX_SOFTWARE; | ||
389 | } | ||
390 | rc = mu_stream_to_message (instr, &msg); | ||
391 | if (rc) | ||
392 | { | ||
393 | mu_error (_("Cannot create message from stream: %s"), | ||
394 | mu_strerror (rc)); | ||
395 | return EX_SOFTWARE; | ||
396 | } | ||
397 | mu_message_get_attribute (msg, &attr); | ||
398 | mu_attribute_unset_deleted (attr); | ||
399 | rc = mu_sieve_message (mach, msg); | ||
400 | if (rc) | ||
401 | /* FIXME: switch (rc)...*/ | ||
402 | return EX_SOFTWARE; | ||
403 | |||
404 | return mu_attribute_is_deleted (attr) ? 1 : EX_OK; | ||
405 | } | ||
406 | |||
407 | static int | ||
408 | sieve_mailbox (mu_sieve_machine_t mach, mu_ticket_t ticket, mu_debug_t debug) | ||
409 | { | ||
410 | int rc; | ||
411 | mu_mailbox_t mbox = NULL; | ||
412 | |||
413 | /* Create, give a ticket to, and open the mailbox. */ | ||
414 | if ((rc = mu_mailbox_create_default (&mbox, mbox_url)) != 0) | ||
415 | { | ||
416 | if (mbox) | ||
417 | mu_error (_("Could not create mailbox `%s': %s"), | ||
418 | mbox_url, mu_strerror (rc)); | ||
419 | else | ||
420 | mu_error (_("Could not create default mailbox: %s"), | ||
421 | mu_strerror (rc)); | ||
422 | goto cleanup; | ||
423 | } | ||
424 | |||
425 | if (debug && (rc = mu_mailbox_set_debug (mbox, debug))) | ||
426 | { | ||
427 | mu_error (_("mu_mailbox_set_debug failed: %s"), mu_strerror (rc)); | ||
428 | goto cleanup; | ||
429 | } | ||
430 | |||
431 | if (ticket) | ||
432 | { | ||
433 | mu_folder_t folder = NULL; | ||
434 | mu_authority_t auth = NULL; | ||
435 | |||
436 | if ((rc = mu_mailbox_get_folder (mbox, &folder))) | ||
437 | { | ||
438 | mu_error (_("mu_mailbox_get_folder failed: %s"), | ||
439 | mu_strerror (rc)); | ||
440 | goto cleanup; | ||
441 | } | ||
442 | |||
443 | if ((rc = mu_folder_get_authority (folder, &auth))) | ||
444 | { | ||
445 | mu_error (_("mu_folder_get_authority failed: %s"), | ||
446 | mu_strerror (rc)); | ||
447 | goto cleanup; | ||
448 | } | ||
449 | |||
450 | /* Authentication-less folders don't have authorities. */ | ||
451 | if (auth && (rc = mu_authority_set_ticket (auth, ticket))) | ||
452 | { | ||
453 | mu_error (_("mu_authority_set_ticket failed: %s"), | ||
454 | mu_strerror (rc)); | ||
455 | goto cleanup; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* Open the mailbox read-only if we aren't going to modify it. */ | ||
460 | if (sieve_debug & MU_SIEVE_DRY_RUN) | ||
461 | rc = mu_mailbox_open (mbox, MU_STREAM_READ); | ||
462 | else | ||
463 | rc = mu_mailbox_open (mbox, MU_STREAM_RDWR); | ||
464 | |||
465 | if (rc != 0) | ||
466 | { | ||
467 | if (mbox) | ||
468 | mu_error (_("Opening mailbox `%s' failed: %s"), | ||
469 | mbox_url, mu_strerror (rc)); | ||
470 | else | ||
471 | mu_error (_("Opening default mailbox failed: %s"), | ||
472 | mu_strerror (rc)); | ||
473 | mu_mailbox_destroy (&mbox); | ||
474 | goto cleanup; | ||
475 | } | ||
476 | |||
477 | /* Process the mailbox */ | ||
478 | rc = mu_sieve_mailbox (mach, mbox); | ||
479 | |||
480 | cleanup: | ||
481 | if (mbox && !(sieve_debug & MU_SIEVE_DRY_RUN)) | ||
482 | { | ||
483 | int e; | ||
484 | |||
485 | /* A message won't be marked deleted unless the script executed | ||
486 | succesfully on it, so we always do an expunge, it will delete | ||
487 | any messages that were marked DELETED even if execution failed | ||
488 | on a later message. */ | ||
489 | if ((e = mu_mailbox_expunge (mbox)) != 0) | ||
490 | { | ||
491 | if (mbox) | ||
492 | mu_error (_("Expunge on mailbox `%s' failed: %s"), | ||
493 | mbox_url, mu_strerror (e)); | ||
494 | else | ||
495 | mu_error (_("Expunge on default mailbox failed: %s"), | ||
496 | mu_strerror (e)); | ||
497 | } | ||
498 | |||
499 | if (e && !rc) | ||
500 | rc = e; | ||
501 | } | ||
502 | |||
503 | mu_sieve_machine_destroy (&mach); | ||
504 | mu_mailbox_close (mbox); | ||
505 | mu_mailbox_destroy (&mbox); | ||
506 | /* FIXME: switch (rc) ... */ | ||
507 | return rc ? EX_SOFTWARE : EX_OK; | ||
508 | } | ||
509 | |||
369 | int | 510 | int |
370 | main (int argc, char *argv[]) | 511 | main (int argc, char *argv[]) |
371 | { | 512 | { |
... | @@ -373,7 +514,6 @@ main (int argc, char *argv[]) | ... | @@ -373,7 +514,6 @@ main (int argc, char *argv[]) |
373 | mu_wicket_t wicket = 0; | 514 | mu_wicket_t wicket = 0; |
374 | mu_ticket_t ticket = 0; | 515 | mu_ticket_t ticket = 0; |
375 | mu_debug_t debug = 0; | 516 | mu_debug_t debug = 0; |
376 | mu_mailbox_t mbox = 0; | ||
377 | int rc; | 517 | int rc; |
378 | 518 | ||
379 | /* Native Language Support */ | 519 | /* Native Language Support */ |
... | @@ -394,14 +534,14 @@ main (int argc, char *argv[]) | ... | @@ -394,14 +534,14 @@ main (int argc, char *argv[]) |
394 | 534 | ||
395 | if (mu_app_init (&argp, sieve_argp_capa, sieve_cfg_param, | 535 | if (mu_app_init (&argp, sieve_argp_capa, sieve_cfg_param, |
396 | argc, argv, ARGP_IN_ORDER, NULL, NULL)) | 536 | argc, argv, ARGP_IN_ORDER, NULL, NULL)) |
397 | exit (1); | 537 | exit (EX_USAGE); |
398 | 538 | ||
399 | /* Sieve interpreter setup. */ | 539 | /* Sieve interpreter setup. */ |
400 | rc = mu_sieve_machine_init (&mach, NULL); | 540 | rc = mu_sieve_machine_init (&mach, NULL); |
401 | if (rc) | 541 | if (rc) |
402 | { | 542 | { |
403 | mu_error (_("Cannot initialize sieve machine: %s"), mu_strerror (rc)); | 543 | mu_error (_("Cannot initialize sieve machine: %s"), mu_strerror (rc)); |
404 | return 1; | 544 | return EX_SOFTWARE; |
405 | } | 545 | } |
406 | 546 | ||
407 | if (mu_log_facility) | 547 | if (mu_log_facility) |
... | @@ -419,14 +559,14 @@ main (int argc, char *argv[]) | ... | @@ -419,14 +559,14 @@ main (int argc, char *argv[]) |
419 | 559 | ||
420 | rc = mu_sieve_compile (mach, script); | 560 | rc = mu_sieve_compile (mach, script); |
421 | if (rc) | 561 | if (rc) |
422 | return 1; | 562 | return EX_CONFIG; |
423 | 563 | ||
424 | /* We can finish if its only a compilation check. */ | 564 | /* We can finish if its only a compilation check. */ |
425 | if (compile_only) | 565 | if (compile_only) |
426 | { | 566 | { |
427 | if (compile_only == 2) | 567 | if (compile_only == 2) |
428 | mu_sieve_disass (mach); | 568 | mu_sieve_disass (mach); |
429 | return 0; | 569 | return EX_OK; |
430 | } | 570 | } |
431 | 571 | ||
432 | /* Create a ticket, if we can. */ | 572 | /* Create a ticket, if we can. */ |
... | @@ -437,14 +577,14 @@ main (int argc, char *argv[]) | ... | @@ -437,14 +577,14 @@ main (int argc, char *argv[]) |
437 | if ((rc = mu_wicket_get_ticket (wicket, &ticket, 0, 0)) != 0) | 577 | if ((rc = mu_wicket_get_ticket (wicket, &ticket, 0, 0)) != 0) |
438 | { | 578 | { |
439 | mu_error (_("ticket_get failed: %s"), mu_strerror (rc)); | 579 | mu_error (_("ticket_get failed: %s"), mu_strerror (rc)); |
440 | goto cleanup; | 580 | return EX_SOFTWARE; /* FIXME: really? */ |
441 | } | 581 | } |
442 | } | 582 | } |
443 | else if (!(tickets_default && errno == ENOENT)) | 583 | else if (!(tickets_default && errno == ENOENT)) |
444 | { | 584 | { |
445 | mu_error (_("mu_wicket_create `%s' failed: %s"), | 585 | mu_error (_("mu_wicket_create `%s' failed: %s"), |
446 | tickets, mu_strerror (rc)); | 586 | tickets, mu_strerror (rc)); |
447 | goto cleanup; | 587 | return EX_SOFTWARE; |
448 | } | 588 | } |
449 | if (ticket) | 589 | if (ticket) |
450 | mu_sieve_set_ticket (mach, ticket); | 590 | mu_sieve_set_ticket (mach, ticket); |
... | @@ -456,114 +596,25 @@ main (int argc, char *argv[]) | ... | @@ -456,114 +596,25 @@ main (int argc, char *argv[]) |
456 | if ((rc = mu_debug_create (&debug, mach))) | 596 | if ((rc = mu_debug_create (&debug, mach))) |
457 | { | 597 | { |
458 | mu_error (_("mu_debug_create failed: %s"), mu_strerror (rc)); | 598 | mu_error (_("mu_debug_create failed: %s"), mu_strerror (rc)); |
459 | goto cleanup; | 599 | return EX_SOFTWARE; |
460 | } | 600 | } |
461 | if ((rc = mu_debug_set_level (debug, debug_level))) | 601 | if ((rc = mu_debug_set_level (debug, debug_level))) |
462 | { | 602 | { |
463 | mu_error (_("mu_debug_set_level failed: %s"), | 603 | mu_error (_("mu_debug_set_level failed: %s"), |
464 | mu_strerror (rc)); | 604 | mu_strerror (rc)); |
465 | goto cleanup; | 605 | return EX_SOFTWARE; |
466 | } | 606 | } |
467 | mu_sieve_set_debug_object (mach, debug); | 607 | mu_sieve_set_debug_object (mach, debug); |
468 | } | 608 | } |
469 | 609 | ||
470 | mu_sieve_set_debug_level (mach, sieve_debug); | 610 | mu_sieve_set_debug_level (mach, sieve_debug); |
471 | |||
472 | /* Create, give a ticket to, and open the mailbox. */ | ||
473 | if ((rc = mu_mailbox_create_default (&mbox, mbox_url)) != 0) | ||
474 | { | ||
475 | if (mbox) | ||
476 | mu_error (_("Could not create mailbox `%s': %s"), | ||
477 | mbox_url, mu_strerror (rc)); | ||
478 | else | ||
479 | mu_error (_("Could not create default mailbox: %s"), | ||
480 | mu_strerror (rc)); | ||
481 | goto cleanup; | ||
482 | } | ||
483 | 611 | ||
484 | if (debug && (rc = mu_mailbox_set_debug (mbox, debug))) | 612 | if (mbox_url && strcmp (mbox_url, "-") == 0) |
485 | { | 613 | rc = sieve_message (mach); |
486 | mu_error (_("mu_mailbox_set_debug failed: %s"), mu_strerror (rc)); | ||
487 | goto cleanup; | ||
488 | } | ||
489 | |||
490 | if (ticket) | ||
491 | { | ||
492 | mu_folder_t folder = NULL; | ||
493 | mu_authority_t auth = NULL; | ||
494 | |||
495 | if ((rc = mu_mailbox_get_folder (mbox, &folder))) | ||
496 | { | ||
497 | mu_error (_("mu_mailbox_get_folder failed: %s"), | ||
498 | mu_strerror (rc)); | ||
499 | goto cleanup; | ||
500 | } | ||
501 | |||
502 | if ((rc = mu_folder_get_authority (folder, &auth))) | ||
503 | { | ||
504 | mu_error (_("mu_folder_get_authority failed: %s"), | ||
505 | mu_strerror (rc)); | ||
506 | goto cleanup; | ||
507 | } | ||
508 | |||
509 | /* Authentication-less folders don't have authorities. */ | ||
510 | if (auth && (rc = mu_authority_set_ticket (auth, ticket))) | ||
511 | { | ||
512 | mu_error (_("mu_authority_set_ticket failed: %s"), | ||
513 | mu_strerror (rc)); | ||
514 | goto cleanup; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | /* Open the mailbox read-only if we aren't going to modify it. */ | ||
519 | if (sieve_debug & MU_SIEVE_DRY_RUN) | ||
520 | rc = mu_mailbox_open (mbox, MU_STREAM_READ); | ||
521 | else | 614 | else |
522 | rc = mu_mailbox_open (mbox, MU_STREAM_RDWR); | 615 | rc = sieve_mailbox (mach, ticket, debug); |
523 | |||
524 | if (rc != 0) | ||
525 | { | ||
526 | if (mbox) | ||
527 | mu_error (_("Opening mailbox `%s' failed: %s"), | ||
528 | mbox_url, mu_strerror (rc)); | ||
529 | else | ||
530 | mu_error (_("Opening default mailbox failed: %s"), | ||
531 | mu_strerror (rc)); | ||
532 | mu_mailbox_destroy (&mbox); | ||
533 | goto cleanup; | ||
534 | } | ||
535 | |||
536 | /* Process the mailbox */ | ||
537 | rc = mu_sieve_mailbox (mach, mbox); | ||
538 | |||
539 | cleanup: | ||
540 | if (mbox && !(sieve_debug & MU_SIEVE_DRY_RUN)) | ||
541 | { | ||
542 | int e; | ||
543 | |||
544 | /* A message won't be marked deleted unless the script executed | ||
545 | succesfully on it, so we always do an expunge, it will delete | ||
546 | any messages that were marked DELETED even if execution failed | ||
547 | on a later message. */ | ||
548 | if ((e = mu_mailbox_expunge (mbox)) != 0) | ||
549 | { | ||
550 | if (mbox) | ||
551 | mu_error (_("Expunge on mailbox `%s' failed: %s"), | ||
552 | mbox_url, mu_strerror (e)); | ||
553 | else | ||
554 | mu_error (_("Expunge on default mailbox failed: %s"), | ||
555 | mu_strerror (e)); | ||
556 | } | ||
557 | |||
558 | if (e && !rc) | ||
559 | rc = e; | ||
560 | } | ||
561 | |||
562 | mu_sieve_machine_destroy (&mach); | ||
563 | mu_mailbox_close (mbox); | ||
564 | mu_mailbox_destroy (&mbox); | ||
565 | mu_debug_destroy (&debug, mach); | 616 | mu_debug_destroy (&debug, mach); |
566 | 617 | ||
567 | return rc ? 1 : 0; | 618 | return rc; |
568 | } | 619 | } |
569 | 620 | ... | ... |
... | @@ -22,7 +22,7 @@ sieve_test i-numeric-is.sv -pattern \ | ... | @@ -22,7 +22,7 @@ sieve_test i-numeric-is.sv -pattern \ |
22 | "DISCARD on msg uid 2: marking as deleted"\ | 22 | "DISCARD on msg uid 2: marking as deleted"\ |
23 | "IMPLICIT KEEP on msg uid 3" | 23 | "IMPLICIT KEEP on msg uid 3" |
24 | 24 | ||
25 | sieve_test i-numeric-contains.sv -retcode 1 -pattern \ | 25 | sieve_test i-numeric-contains.sv -retcode 78 -pattern \ |
26 | -re ".*i-numeric-contains.sv:9: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header'" | 26 | -re ".*i-numeric-contains.sv:9: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header'" |
27 | 27 | ||
28 | # end of i-numeric.exp | 28 | # end of i-numeric.exp | ... | ... |
-
Please register or sign in to post a comment