#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 92 "mbox.bi"
static mu_debug_handle_t debug_handle;
#line 1026 "../../src/builtin/snarf.m4"

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

/* End of snarf.m4 */
#line 1 "mbox.bi"
/* This file is part of Mailfromd.             -*- c -*-
   Copyright (C) 2008-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 "msg.h"
#include "global.h"

static size_t nmboxes = MAX_MBOXES;

static struct mu_cfg_param mbox_cfg_param[] = {
	{ "max-open-mailboxes", mu_c_size, &nmboxes, 0, NULL,
	  N_("Maximum number of mailboxes to open simultaneously.") },
	{ NULL }
};

static int
do_close(void *item, void *data)
{
	bi_close_message(item);
	return 0;
}

static void
close_mbox(struct mf_mbox *mp)
{
	if (mp->mbox) {
		mu_mailbox_close(mp->mbox);
		mu_mailbox_destroy(&mp->mbox);
		mu_list_foreach(mp->msglist, do_close, NULL);
		mu_list_destroy(&mp->msglist);
		memset(mp, 0, sizeof mp[0]);
	}
}

static void *
alloc_mboxes()
{
	return mu_calloc(nmboxes, sizeof(struct mf_mbox));
}

static void
destroy_mboxes(void *data)
{
	struct mf_mbox *mtab = data;
	struct mf_mbox *p;
	for (p = mtab; p < mtab + nmboxes; p++) {
		close_mbox(p);
	}
	free(mtab);
}


#line 66

#line 66
static int MBOXTAB_id;
#line 66 "mbox.bi"


static int
find_slot(struct mf_mbox *tab)
{
	int i;
	for (i = 0; i < nmboxes; i++)
		if (tab[i].mbox == NULL)
			return i;
	return -1;
}

/* number mailbox_open(string url) */
void
#line 79
bi_mailbox_open(eval_environ_t env)
#line 79

#line 79

#line 79 "mbox.bi"
{
#line 79
	
#line 79

#line 79
        char *  url;
#line 79
        char *  mode;
#line 79
        char *  perms;
#line 79
        
#line 79
        long __bi_argcnt;
#line 79
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 79
        get_string_arg(env, 1, &url);
#line 79
        if (__bi_argcnt > 1)
#line 79
                get_string_arg(env, 2, &mode);
#line 79
        if (__bi_argcnt > 2)
#line 79
                get_string_arg(env, 3, &perms);
#line 79
        
#line 79
        adjust_stack(env, __bi_argcnt + 1);
#line 79

#line 79

#line 79
	if (builtin_module_trace(BUILTIN_IDX_mbox))
#line 79
		prog_trace(env, "mailbox_open %s %s %s",url, ((__bi_argcnt > 1) ? mode : ""), ((__bi_argcnt > 2) ? perms : ""));;
#line 79

{
	int rc;
	int md;
	struct mf_mbox *mbtab = env_get_builtin_priv(env,MBOXTAB_id);
	struct mf_mbox *mp;
	int flags;
	char *p;

	md = find_slot(mbtab);
		if (!(md >= 0))
#line 89
		(
#line 89
	env_throw_bi(env, mfe_failure, "mailbox_open", _("no more mailboxes available"))
#line 89
)
#line 91
;
	
#line 92 "mbox.bi"

#line 92
mu_debug(debug_handle, MU_DEBUG_TRACE1,("opening mailbox %s", url));
	mp = mbtab + md;

	flags = 0;
	for (p = ((__bi_argcnt > 1) ? mode : "r"); *p; p++) {
		switch (*p) {
		case 'a':
			flags |= MU_STREAM_APPEND;
			break;
			
		case 'r':
			flags |= MU_STREAM_READ;
			break;
			
		case 'w':
			flags |= MU_STREAM_WRITE;
			break;
			
		case '+':
			if (flags & MU_STREAM_READ)
				flags |= MU_STREAM_WRITE;
			else if (flags & MU_STREAM_WRITE)
				/* FIXME: should truncate as well */
				flags |= MU_STREAM_READ|MU_STREAM_CREAT;
			else if (flags & MU_STREAM_APPEND) {
				flags |= MU_STREAM_RDWR | MU_STREAM_CREAT;
			} else
				(
#line 119
	env_throw_bi(env, mfe_range, "mailbox_open", _("incorrect mode near `%s'"),p)
#line 119
);
#line 122
			break;

		default:
			(
#line 125
	env_throw_bi(env, mfe_range, "mailbox_open", _("incorrect mode near `%s'"),p)
#line 125
);
#line 128
		}
	}

	if ((__bi_argcnt > 2)) {
		int f;
		const char *p;
			if (!(mu_parse_stream_perm_string(&f, ((__bi_argcnt > 2) ? perms : 0), &p)
#line 134
			  == 0))
#line 134
		(
#line 134
	env_throw_bi(env, mfe_range, "mailbox_open", /* FIXME: introduce mfe_inval? */
			  _("invalid permissions (near %s)"),p)
#line 134
)
#line 137
;
		flags |= f;
	}
		
	rc = mu_mailbox_create(&mp->mbox, url);
		if (!(rc == 0))
#line 142
		(
#line 142
	env_throw_bi(env, mfe_failure, "mailbox_open", _("cannot create mailbox `%s': %s"),url,mu_strerror(rc))
#line 142
)
#line 145
;
	rc = mu_mailbox_open(mp->mbox, flags);
	if (rc) {
		mu_mailbox_destroy(&mp->mbox);
		(
#line 149
	env_throw_bi(env, mfe_failure, "mailbox_open", _("cannot open mailbox `%s': %s"),url,mu_strerror(rc))
#line 149
);
#line 152
	}
	mu_list_create(&mp->msglist);
	
	
#line 155
do {
#line 155
  push(env, (STKVAL)(mft_number)(md));
#line 155
  goto endlab;
#line 155
} while (0);
}
endlab:
#line 157
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 157
	return;
#line 157
}

/* void mailbox_close(number mbx) */
void
#line 160
bi_mailbox_close(eval_environ_t env)
#line 160

#line 160

#line 160 "mbox.bi"
{
#line 160
	
#line 160

#line 160
        long  md;
#line 160
        
#line 160

#line 160
        get_numeric_arg(env, 0, &md);
#line 160
        
#line 160
        adjust_stack(env, 1);
#line 160

#line 160

#line 160
	if (builtin_module_trace(BUILTIN_IDX_mbox))
#line 160
		prog_trace(env, "mailbox_close %lu",md);;
#line 160

{
	struct mf_mbox *mbtab = env_get_builtin_priv(env,MBOXTAB_id);

		if (!(md >= 0 && md < nmboxes))
#line 164
		(
#line 164
	env_throw_bi(env, mfe_range, "mailbox_close", _("invalid mailbox descriptor"))
#line 164
)
#line 166
;
	close_mbox(mbtab + md);
}

#line 169
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 169
	return;
#line 169
}

#line 182

	
/* number mailbox_messages_count(number mbx) */
void
#line 185
bi_mailbox_messages_count(eval_environ_t env)
#line 185

#line 185

#line 185 "mbox.bi"
{
#line 185
	
#line 185

#line 185
        long  nmbx;
#line 185
        
#line 185

#line 185
        get_numeric_arg(env, 0, &nmbx);
#line 185
        
#line 185
        adjust_stack(env, 1);
#line 185

#line 185

#line 185
	if (builtin_module_trace(BUILTIN_IDX_mbox))
#line 185
		prog_trace(env, "mailbox_messages_count %lu",nmbx);;
#line 185

{
	size_t count;
	int rc;
	
#line 189
	struct mf_mbox *mbtab = env_get_builtin_priv(env,MBOXTAB_id);
#line 189
	struct mf_mbox *mp;
#line 189
			
#line 189
		if (!(nmbx >= 0 && nmbx < nmboxes))
#line 189
		(
#line 189
	env_throw_bi(env, mfe_range, "mailbox_messages_count", _("invalid mailbox descriptor"))
#line 189
)
#line 189
;
#line 189
	mp = mbtab + nmbx;
#line 189
		if (!(mp->mbox))
#line 189
		(
#line 189
	env_throw_bi(env, mfe_failure, "mailbox_messages_count", _("mailbox not open"))
#line 189
)
#line 189

#line 189
;
	
	rc = mu_mailbox_messages_count(mp->mbox, &count);
		if (!(rc == 0))
#line 192
		(
#line 192
	env_throw_bi(env, mfe_failure, "mailbox_messages_count", "%s",mu_strerror(rc))
#line 192
)
#line 195
;
	
#line 196
do {
#line 196
  push(env, (STKVAL)(mft_number)(count));
#line 196
  goto endlab;
#line 196
} while (0);
}
endlab:
#line 198
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 198
	return;
#line 198
}

/* number mailbox_get_message(number mbx, number msg-no) */
void
#line 201
bi_mailbox_get_message(eval_environ_t env)
#line 201

#line 201

#line 201 "mbox.bi"
{
#line 201
	
#line 201

#line 201
        long  nmbx;
#line 201
        long  msgno;
#line 201
        
#line 201

#line 201
        get_numeric_arg(env, 0, &nmbx);
#line 201
        get_numeric_arg(env, 1, &msgno);
#line 201
        
#line 201
        adjust_stack(env, 2);
#line 201

#line 201

#line 201
	if (builtin_module_trace(BUILTIN_IDX_mbox))
#line 201
		prog_trace(env, "mailbox_get_message %lu %lu",nmbx, msgno);;
#line 201

{
	int rc;
	mu_message_t msg;
	
#line 205
	struct mf_mbox *mbtab = env_get_builtin_priv(env,MBOXTAB_id);
#line 205
	struct mf_mbox *mp;
#line 205
			
#line 205
		if (!(nmbx >= 0 && nmbx < nmboxes))
#line 205
		(
#line 205
	env_throw_bi(env, mfe_range, "mailbox_get_message", _("invalid mailbox descriptor"))
#line 205
)
#line 205
;
#line 205
	mp = mbtab + nmbx;
#line 205
		if (!(mp->mbox))
#line 205
		(
#line 205
	env_throw_bi(env, mfe_failure, "mailbox_get_message", _("mailbox not open"))
#line 205
)
#line 205

#line 205
;

	rc = mu_mailbox_get_message(mp->mbox, msgno, &msg);
		if (!(rc == 0))
#line 208
		(
#line 208
	env_throw_bi(env, mfe_failure, "mailbox_get_message", "%s",mu_strerror(rc))
#line 208
)
#line 211
;
	rc = bi_message_register(env, mp->msglist, msg, MF_MSG_MAILBOX);
		if (!(rc >= 0))
#line 213
		(
#line 213
	env_throw_bi(env, mfe_failure, "mailbox_get_message", _("no more message slots available"))
#line 213
)
#line 215
;
	
#line 216
do {
#line 216
  push(env, (STKVAL)(mft_number)(rc));
#line 216
  goto endlab;
#line 216
} while (0);
}
endlab:
#line 218
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 218
	return;
#line 218
}

/* void mailbox_append_message(number mbx, number msg-no) */
void
#line 221
bi_mailbox_append_message(eval_environ_t env)
#line 221

#line 221

#line 221 "mbox.bi"
{
#line 221
	
#line 221

#line 221
        long  nmbx;
#line 221
        long  msgno;
#line 221
        
#line 221

#line 221
        get_numeric_arg(env, 0, &nmbx);
#line 221
        get_numeric_arg(env, 1, &msgno);
#line 221
        
#line 221
        adjust_stack(env, 2);
#line 221

#line 221

#line 221
	if (builtin_module_trace(BUILTIN_IDX_mbox))
#line 221
		prog_trace(env, "mailbox_append_message %lu %lu",nmbx, msgno);;
#line 221

{
	int rc;
	mu_message_t msg;
	
#line 225
	struct mf_mbox *mbtab = env_get_builtin_priv(env,MBOXTAB_id);
#line 225
	struct mf_mbox *mp;
#line 225
			
#line 225
		if (!(nmbx >= 0 && nmbx < nmboxes))
#line 225
		(
#line 225
	env_throw_bi(env, mfe_range, "mailbox_append_message", _("invalid mailbox descriptor"))
#line 225
)
#line 225
;
#line 225
	mp = mbtab + nmbx;
#line 225
		if (!(mp->mbox))
#line 225
		(
#line 225
	env_throw_bi(env, mfe_failure, "mailbox_append_message", _("mailbox not open"))
#line 225
)
#line 225

#line 225
;

	msg = bi_message_from_descr(env, msgno);
	rc = mu_mailbox_append_message(mp->mbox, msg);
		if (!(rc == 0))
#line 229
		(
#line 229
	env_throw_bi(env, mfe_failure, "mailbox_append_message", _("cannot append message: %s"),mu_strerror(rc))
#line 229
)
#line 232
;
}

#line 234
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 234
	return;
#line 234
}

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

#line 1026

#line 1026

#line 1026
void
#line 1026
mbox_init_builtin(void)
#line 1026
{
#line 1026
		debug_handle = mu_debug_register_category("bi_mbox");
#line 1026

#line 1026
	#line 66 "mbox.bi"
MBOXTAB_id = builtin_priv_register(alloc_mboxes, destroy_mboxes,
#line 66
NULL);
#line 79 "mbox.bi"
va_builtin_install_ex("mailbox_open", bi_mailbox_open, 0, dtype_number, 3, 2, 0|0, dtype_string, dtype_string, dtype_string);
#line 160 "mbox.bi"
va_builtin_install_ex("mailbox_close", bi_mailbox_close, 0, dtype_unspecified, 1, 0, 0|0, dtype_number);
#line 185 "mbox.bi"
va_builtin_install_ex("mailbox_messages_count", bi_mailbox_messages_count, 0, dtype_number, 1, 0, 0|0, dtype_number);
#line 201 "mbox.bi"
va_builtin_install_ex("mailbox_get_message", bi_mailbox_get_message, 0, dtype_number, 2, 0, 0|0, dtype_number, dtype_number);
#line 221 "mbox.bi"
va_builtin_install_ex("mailbox_append_message", bi_mailbox_append_message, 0, dtype_unspecified, 2, 0, 0|0, dtype_number, dtype_number);

#line 1026 "../../src/builtin/snarf.m4"
	
#line 1026
	 mf_add_runtime_params(mbox_cfg_param);
#line 1026
	 
#line 1026
}
#line 1026 "../../src/builtin/snarf.m4"

