-/*
- * 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 2 of the License, 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Copyright © 2007 Pierre Habouzit
- */
-
-#include <lib-lib/lib-lib.h>
-
-#include <sys/types.h>
-#include <pwd.h>
-
-#include "lib-lua_priv.h"
-
-#include "../mutt.h"
-
-/* {{{ madmutt functions */
-
-static int madmutt_pwd(lua_State *L)
-{
- char path[_POSIX_PATH_MAX];
- getcwd(path, sizeof(path));
- lua_pushstring(L, path);
- return 1;
-}
-
-static int madmutt_folder_path(lua_State *L)
-{
- lua_pushstring(L, CurrentFolder ?: "");
- return 1;
-}
-
-static int madmutt_folder_name(lua_State *L)
-{
- const char *p;
-
- if (!m_strisempty(Maildir)
- && m_strstart(CurrentFolder, Maildir, &p) && *p) {
- while (*p == '/')
- p++;
- lua_pushstring(L, p);
- } else {
- p = strchr(CurrentFolder ?: "", '/');
- lua_pushstring(L, p ? p + 1 : (CurrentFolder ?: ""));
- }
- return 1;
-}
-
-static quadopt_t quadopt_parse(const char *s)
-{
- if (!m_strcasecmp("yes", s))
- return M_YES;
- if (!m_strcasecmp("no", s))
- return M_NO;
- if (!m_strcasecmp("ask-yes", s))
- return M_ASKYES;
- if (!m_strcasecmp("ask-no", s))
- return M_ASKNO;
- return -1;
-}
-
-static int madmutt_assign(lua_State *L)
-{
- const char *idx = luaL_checkstring(L, 2);
- const char *val = luaL_checkstring(L, 3);
- int tk;
-
- switch ((tk = lua_which_token(idx, -1))) {
- char buf[STRING];
- int i;
-
- case LTK_DOTLOCK:
- case LTK_SENDMAIL:
- case LTK_SHELL:
- case LTK_EDITOR:
- _mutt_expand_path(buf, sizeof(buf), val, 0);
- val = buf;
- /* FALLTHROUGH */
-
- mlua_regsets(tk, val);
- return 0;
-
- case LTK_QUIT:
- i = quadopt_parse(val);
- if (i < 0)
- return luaL_error(L, "invalid quad option value: '%s'", val);
- mlua_regseti(tk, i);
- return 0;
-
- case LTK_UNKNOWN:
- case LTK_count:
- break;
- }
-
- return luaL_error(L, "read-only or inexistant property '%s'", idx, tk);
-}
-
-static int madmutt_get(lua_State *L)
-{
- const char *idx = luaL_checkstring(L, 2);
- enum lua_token tk = lua_which_token(idx, -1);
-
- switch (tk) {
- case LTK_DOTLOCK:
- case LTK_SENDMAIL:
- case LTK_SHELL:
- case LTK_EDITOR:
- lua_pushstring(L, mlua_reggets(tk));
- return 1;
-
- case LTK_QUIT:
- switch (mlua_reggeti(tk)) {
- case M_YES:
- lua_pushstring(L, "yes");
- return 1;
- case M_NO:
- lua_pushstring(L, "no");
- return 1;
- case M_ASKNO:
- lua_pushstring(L, "ask-no");
- return 1;
- case M_ASKYES:
- lua_pushstring(L, "ask-yes");
- return 1;
- default:
- return 0;
- }
-
- case LTK_UNKNOWN:
- case LTK_count:
- break;
- }
-
- lua_getmetatable(L, 1);
- lua_replace(L, 1);
- lua_rawget(L, 1);
- return 1;
-}
-
-static const struct luaL_Reg madmutt_module_funcs[] = {
- { "pwd", madmutt_pwd },
- /*
- ** .pp
- ** \fIThis is a read-only system property and, at runtime,
- ** specifies the current working directory of the madmutt
- ** binary.\fP
- */
- { "folder_path", madmutt_folder_path },
- /*
- ** .pp
- ** \fIThis is a read-only system property and, at runtime,
- ** specifies the full path or URI of the folder currently
- ** open (if any).\fP
- */
- { "folder_name", madmutt_folder_name },
- /*
- ** .pp
- ** \fIThis is a read-only system property and, at runtime,
- ** specifies the actual name of the folder as far as it could
- ** be detected.\fP
- ** .pp
- ** For detection, $$$folder is first taken into account
- ** and simply stripped to form the result when a match is found. For
- ** example, with $$$folder being \fTimap://host\fP and the folder is
- ** \fTimap://host/INBOX/foo\fP, $$$madmutt_folder_name will be just
- ** \fTINBOX/foo\fP.)
- ** .pp
- ** Second, if the initial portion of a name is not $$$folder,
- ** the result will be everything after the last ``/''.
- ** .pp
- ** Third and last, the result will be just the name if neither
- ** $$$folder nor a ``/'' were found in the name.
- */
-
- { "__newindex", madmutt_assign },
- { "__index", madmutt_get },
- { NULL, NULL }
-};
-
-/* }}} */
-
-/* {{{ read-only properties */
-
-static const struct {
- const char *key;
- const char *value;
-} madmutt_module_vars[] = {
- { "version", VERSION },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies madmutt's
- ** version string.\fP
- */
- { "sysconfdir", SYSCONFDIR },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies madmutt's
- ** subversion revision string.\fP
- */
- { "bindir", BINDIR },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies the
- ** directory containing the madmutt binary.\fP
- */
- { "docdir", PKGDOCDIR },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies the
- ** directory containing the madmutt documentation.\fP
- */
-#ifdef USE_HCACHE
-#if defined(HAVE_QDBM)
- { "hcache_backend", "qdbm" },
-#elif defined(HAVE_GDBM)
- { "hcache_backend", "gdbm" },
-#elif defined(HAVE_DB4)
- { "hcache_backend", "db4" },
-#else
- { "hcache_backend", "unknown" },
-#endif
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies the
- ** header chaching's database backend.\fP
- */
-#endif
-};
-
-/* }}} */
-
-/* {{{ madmutt magic properties */
-
-static void madmutt_init_editor(char *buf, ssize_t len)
-{
- m_strcpy(buf, len, getenv("VISUAL") ?: getenv("EDITOR") ?: "vi");
-}
-
-static void madmutt_init_shell(char *buf, ssize_t len)
-{
- struct passwd *pw = getpwuid(getuid());
-
- if (pw) {
- m_strcpy(buf, len, pw->pw_shell);
- _mutt_expand_path(buf, len, pw->pw_shell, 0);
- } else {
- m_strcpy(buf, len, getenv("SHELL") ?: "/bin/sh");
- }
-}
-
-static const struct {
- const char *key;
- void (*fun)(char *buf, ssize_t len);
- const char *val;
-} madmutt_module_vars2[] = {
- { "dotlock", NULL, BINDIR "/mutt_dotlock" },
- /*
- ** .pp
- ** Contains the path of the \fTmadmutt_dotlock(1)\fP binary to be used by
- ** Madmutt.
- */
- { "editor", madmutt_init_editor, NULL },
- /*
- ** .pp
- ** This variable specifies which editor is used by Madmutt.
- ** It defaults to the value of the \fT$$$VISUAL\fP, or \fT$$$EDITOR\fP, environment
- ** variable, or to the string "\fTvi\fP" if neither of those are set.
- */
- { "sendmail", NULL, SENDMAIL " -oem -oi" },
- /*
- ** .pp
- ** Specifies the program and arguments used to deliver mail sent by Madmutt.
- ** Madmutt expects that the specified program interprets additional
- ** arguments as recipient addresses.
- */
- { "shell", madmutt_init_shell, NULL },
- /*
- ** .pp
- ** Command to use when spawning a subshell. By default, the user's login
- ** shell from \fT/etc/passwd\fP is used.
- */
- { "quit", NULL, "yes" },
- /*
- ** .pp
- ** This variable controls whether ``quit'' and ``exit'' actually quit
- ** from Madmutt. If it set to \fIyes\fP, they do quit, if it is set to \fIno\fP, they
- ** have no effect, and if it is set to \fIask-yes\fP or \fIask-no\fP, you are
- ** prompted for confirmation when you try to quit.
- */
-};
-
-/* }}} */
-
-int luaopen_madmutt(lua_State *L)
-{
- int i;
-
- lua_newuserdata(L, sizeof(void*));
- luaL_newmetatable(L, "madmutt.core");
-
- luaL_openlib(L, NULL, madmutt_module_funcs, 0);
-
- for (i = 0; i < countof(madmutt_module_vars); i++) {
- lua_pushstring(L, madmutt_module_vars[i].value);
- lua_setfield(L, -2, madmutt_module_vars[i].key);
- }
-
- lua_setmetatable(L, -2);
-
- for (i = 0; i < countof(madmutt_module_vars2); i++) {
- if (madmutt_module_vars2[i].fun) {
- char buf[STRING];
- (madmutt_module_vars2[i].fun)(buf, sizeof(buf));
- lua_pushstring(L, buf);
- } else {
- lua_pushstring(L, madmutt_module_vars2[i].val);
- }
- lua_setfield(L, -2, madmutt_module_vars2[i].key);
- }
-
- lua_setglobal(L, "madmutt");
- return 1;
-}