/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file */ #include "lib.h" #include "lib-signals.h" #include "ioloop.h" #include "ostream.h" #include "hostpid.h" #include "mail-storage.h" #include "sieve.h" #include "sieve-tool.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <pwd.h> /* * Global state */ static struct ioloop *ioloop; /* * Signal handlers */ static void sig_die(const siginfo_t *si, void *context ATTR_UNUSED) { /* warn about being killed because of some signal, except SIGINT (^C) * which is too common at least while testing :) */ if (si->si_signo != SIGINT) { /* FIMXE: strange error for a command line tool */ i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)", si->si_signo, dec2str(si->si_pid), dec2str(si->si_uid), lib_signal_code_to_str(si->si_signo, si->si_code)); } io_loop_stop(current_ioloop); } /* * Initialization */ void sieve_tool_init(void) { lib_init(); ioloop = io_loop_create(); lib_signals_init(); lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL); lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL); lib_signals_ignore(SIGPIPE, TRUE); lib_signals_ignore(SIGALRM, FALSE); if ( !sieve_init() ) i_fatal("failed to initialize sieve implementation\n"); } void sieve_tool_deinit(void) { sieve_deinit(); lib_signals_deinit(); io_loop_destroy(&ioloop); lib_deinit(); } /* * Commonly needed functionality */ const char *sieve_tool_get_user(void) { const char *user; uid_t process_euid; struct passwd *pw; user = getenv("USER"); if ( user == NULL || *user == '\0' ) { process_euid = geteuid(); if ((pw = getpwuid(process_euid)) != NULL) { user = t_strdup(pw->pw_name); } if ( user == NULL || *user == '\0' ) { i_fatal("couldn't lookup our username (uid=%s)", dec2str(process_euid)); } } return user; } void sieve_tool_get_envelope_data (struct mail *mail, const char **recipient, const char **sender) { /* Get recipient address */ if ( *recipient == NULL ) (void)mail_get_first_header(mail, "Envelope-To", recipient); if ( *recipient == NULL ) (void)mail_get_first_header(mail, "To", recipient); if ( *recipient == NULL ) *recipient = "recipient@example.com"; /* Get sender address */ if ( *sender == NULL ) (void)mail_get_first_header(mail, "Return-path", sender); if ( *sender == NULL ) (void)mail_get_first_header(mail, "Sender", sender); if ( *sender == NULL ) (void)mail_get_first_header(mail, "From", sender); if ( *sender == NULL ) *sender = "sender@example.com"; } /* * Sieve script handling */ struct sieve_binary *sieve_tool_script_compile (const char *filename, const char *name) { struct sieve_error_handler *ehandler; struct sieve_binary *sbin; ehandler = sieve_stderr_ehandler_create(0); sieve_error_handler_accept_infolog(ehandler, TRUE); if ( (sbin = sieve_compile(filename, name, ehandler)) == NULL ) i_error("failed to compile sieve script '%s'\n", filename); sieve_error_handler_unref(&ehandler); return sbin; } struct sieve_binary *sieve_tool_script_open(const char *filename) { struct sieve_error_handler *ehandler; struct sieve_binary *sbin; ehandler = sieve_stderr_ehandler_create(0); sieve_error_handler_accept_infolog(ehandler, TRUE); if ( (sbin = sieve_open(filename, NULL, ehandler, NULL)) == NULL ) { sieve_error_handler_unref(&ehandler); i_fatal("Failed to compile sieve script\n"); } sieve_error_handler_unref(&ehandler); return sbin; } void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename) { int dfd = -1; struct ostream *dumpstream; if ( filename == NULL ) return; if ( strcmp(filename, "-") == 0 ) dumpstream = o_stream_create_fd(1, 0, FALSE); else { if ( (dfd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0 ) { i_fatal("failed to open dump-file for writing: %m"); } dumpstream = o_stream_create_fd(dfd, 0, FALSE); } if ( dumpstream != NULL ) { (void) sieve_dump(sbin, dumpstream); o_stream_destroy(&dumpstream); } else { i_fatal("Failed to create stream for sieve code dump."); } if ( dfd != -1 ) close(dfd); }