Commit 7cc7c42f 7cc7c42fc2fba3e9113438320ea4d78041ec44d7 by Sergey Poznyakoff

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.
1 parent 23160352
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
......