#line 1026 "../../src/builtin/snarf.m4"
/* -*- buffer-read-only: t -*- vi: set ro:
   THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
*/
#line 1026
#ifdef HAVE_CONFIG_H
#line 1026
# include <config.h>
#line 1026
#endif
#line 1026
#include <sys/types.h>
#line 1026

#line 1026
#include "mailfromd.h"
#line 1026
#include "prog.h"
#line 1026
#include "builtin.h"
#line 1026

#line 1026

#line 1066 "../../src/builtin/snarf.m4"

/* End of snarf.m4 */
#line 1 "sieve.bi"
/* This file is part of Mailfromd.             -*- c -*-
   Copyright (C) 2007-2025 Sergey Poznyakoff

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */



#include <mailutils/mailutils.h>
#include <mflib/sieve.h>
#include "msg.h"

static void
_sieve_text_action_log(mu_sieve_machine_t mach,
		       const char *action, const char *fmt, va_list ap)
{
	mu_stream_t stream;
	eval_environ_t env = mu_sieve_get_data (mach);
	const char *id;

	mu_sieve_get_diag_stream(mach, &stream);
	mu_stream_printf(stream, "\033s<%d>", MU_LOG_NOTICE);
	id = mailfromd_msgid(env_get_context(env));
	if (id && id[0])
		/* ID includes trailing semicolon */
		mu_stream_printf(stream, "%s", id);
	mu_stream_printf(stream, "%s", action);
	if (fmt && fmt[0]) {
		mu_stream_printf(stream, "; ");
		mu_stream_vprintf(stream, fmt, ap);
	}
	mu_stream_printf(stream, "\n");
}

static void
_sieve_file_action_log(mu_sieve_machine_t mach,
		       const char *action, const char *fmt, va_list ap)
{
	mu_stream_t stream;
	eval_environ_t env = mu_sieve_get_data(mach);
	struct mu_locus_range locus;

	_sieve_text_action_log(mach, action, fmt, ap);

	mu_sieve_get_diag_stream(mach, &stream);
	env_get_locus(env, &locus);
	mu_stream_printf(stream, "\033f<%lu>%s\033l<%u>\033s<%d>\033O<%d>%s\n",
			 (unsigned long) strlen(locus.beg.mu_file),
			 locus.beg.mu_file,
			 locus.beg.mu_line,
			 MU_LOG_NOTICE,
		         MU_LOGMODE_LOCUS|MU_LOGMODE_SEVERITY,
			 _("sieve called from here"));
}

static void
mach_cleanup(void *ptr)
{
	mu_sieve_machine_t mach = ptr;
	mu_sieve_machine_destroy(&mach);
}

static void
modify_debug_flags(mu_debug_level_t set, mu_debug_level_t clr)
{
	mu_debug_level_t lev;
  
	mu_debug_get_category_level(mu_sieve_debug_handle, &lev);
	mu_debug_set_category_level(mu_sieve_debug_handle, (lev & ~clr) | set);
}

void
#line 82
bi_sieve(eval_environ_t env)
#line 82

#line 82

#line 82 "sieve.bi"
{
#line 82
	
#line 82

#line 82
        long  nmsg;
#line 82
        char *  script;
#line 82
        long  flags;
#line 82
        char *  file;
#line 82
        long  line;
#line 82
        long  col;
#line 82
        
#line 82
        long __bi_argcnt;
#line 82
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 82
        get_numeric_arg(env, 1, &nmsg);
#line 82
        get_string_arg(env, 2, &script);
#line 82
        if (__bi_argcnt > 2)
#line 82
                get_numeric_arg(env, 3, &flags);
#line 82
        if (__bi_argcnt > 3)
#line 82
                get_string_arg(env, 4, &file);
#line 82
        if (__bi_argcnt > 4)
#line 82
                get_numeric_arg(env, 5, &line);
#line 82
        if (__bi_argcnt > 5)
#line 82
                get_numeric_arg(env, 6, &col);
#line 82
        
#line 82
        adjust_stack(env, __bi_argcnt + 1);
#line 82

#line 82

#line 82
	if (builtin_module_trace(BUILTIN_IDX_sieve))
#line 82
		prog_trace(env, "sieve %lu %s %lu %s %lu %lu",nmsg, script, ((__bi_argcnt > 2) ? flags : 0), ((__bi_argcnt > 3) ? file : ""), ((__bi_argcnt > 4) ? line : 0), ((__bi_argcnt > 5) ? col : 0));;

{
	mu_sieve_machine_t mach;
	int rc;
	int retval = 0;
	int f = ((__bi_argcnt > 2) ? flags : 0);
	mu_attribute_t attr;
	mu_message_t msg;
	const char *s;
	
	rc = mu_sieve_machine_create(&mach);
		if (!(rc == 0))
#line 94
		(
#line 94
	env_throw_bi(env, mfe_failure, "sieve", _("failed to initialize sieve machine: %s"),mu_strerror(rc))
#line 94
)
#line 96
;
	env_function_cleanup_add(env, CLEANUP_ALWAYS, mach, mach_cleanup);
	
	if (f & MF_SIEVE_DEBUG_TRACE)
		modify_debug_flags(MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE4), 0);
	if (f & MF_SIEVE_DEBUG_INSTR)
		modify_debug_flags(MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE9), 0);

	mu_sieve_set_environ(mach, "location", "MTA");
	mu_sieve_set_environ(mach, "phase", "pre");
	s = env_get_macro(env, "client_addr");
	if (s)
		mu_sieve_set_environ(mach, "remote-ip", s);
	s = env_get_macro(env, "client_ptr");
	if (s)
		mu_sieve_set_environ(mach, "remote-host", s);
	
	mu_sieve_set_data(mach, env);

	if (f & MF_SIEVE_TEXT) {
		struct mu_locus_range locus = MU_LOCUS_RANGE_INITIALIZER;
		struct mu_locus_point pt;
		
		env_get_locus(env, &locus);
		if (f & MF_SIEVE_LOG)
			mu_sieve_set_logger(mach, _sieve_text_action_log);
		pt.mu_file = ((__bi_argcnt > 3) ? file : locus.beg.mu_file);
		pt.mu_line = ((__bi_argcnt > 4) ? line : locus.beg.mu_line);
		pt.mu_col = ((__bi_argcnt > 5) ? col : locus.beg.mu_col);
		rc = mu_sieve_compile_text(mach, script, strlen(script), &pt);
	} else {
		if (f & MF_SIEVE_LOG)
			mu_sieve_set_logger(mach, _sieve_file_action_log);
		rc = mu_sieve_compile(mach, script);
	}

		if (!(rc == 0))
#line 132
		(
#line 132
	env_throw_bi(env, mfe_failure, "sieve", _("compilation of Sieve script %s failed"),script)
#line 132
)
#line 135
;

	msg = bi_message_from_descr(env, nmsg);
		
	mu_message_get_attribute(msg, &attr);
	mu_attribute_unset_deleted(attr);
	rc = mu_sieve_message(mach, msg);
		if (!(rc == 0))
#line 142
		(
#line 142
	env_throw_bi(env, mfe_failure, "sieve", _("sieving failed: %s"),mu_strerror(rc))
#line 142
)
#line 145
;
	retval = !(mu_attribute_is_deleted(attr) == 0);

	
#line 148
do {
#line 148
  push(env, (STKVAL)(mft_number)(retval));
#line 148
  goto endlab;
#line 148
} while (0);
}
endlab:
#line 150
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 150
	return;
#line 150
}

#line 1026 "../../src/builtin/snarf.m4"

#line 1026

#line 1026

#line 1026
void
#line 1026
sieve_init_builtin(void)
#line 1026
{
#line 1026
	
#line 1026
	#line 82 "sieve.bi"
va_builtin_install_ex("sieve", bi_sieve, 0, dtype_number, 6, 4, 0|0, dtype_number, dtype_string, dtype_number, dtype_string, dtype_number, dtype_number);

#line 1026 "../../src/builtin/snarf.m4"
	
#line 1026
}
#line 1026 "../../src/builtin/snarf.m4"

