Add tokyocabinet support
[apps/madmutt.git] / lib-lua / madmutt.cpkg
index 270e198..b47a867 100644 (file)
  */
 
 #include <lib-lib/lib-lib.h>
-#include <lib-lua/lib-lua.h>
 
+#include <sys/utsname.h>
 #include <sys/types.h>
 #include <pwd.h>
 
+#include <lib-lua/lib-lua.h>
+#include <lib-ui/lib-ui.h>
+#include <lib-sys/unix.h>
+
 #include "../mutt.h"
+@import "base.cpkg"
 
 static char *madmutt_init_shell(void)
 {
@@ -43,82 +48,361 @@ static char *madmutt_init_homedir(void)
     return m_strdup(pw ? pw->pw_dir : (getenv("HOME") ?: "/"));
 }
 
-static const char *madmutt_pwd(void)
+static char *madmutt_init_shorthost(void)
 {
-    char path[_POSIX_PATH_MAX];
-    getcwd(path, sizeof(path));
-    return path;
+    struct utsname utsname;
+    const char *p;
+
+    /* some systems report the FQDN instead of just the hostname */
+    uname(&utsname);
+    p = m_strchrnul(utsname.nodename, '.');
+    return p_dupstr(utsname.nodename, p - utsname.nodename);
 }
 
-static const char *luaM_path_post(const char *val)
+static char *madmutt_init_os(void)
 {
-    char path[PATH_MAX];
-    _mutt_expand_path(path, sizeof(path), val, 0);
-    return path;
+    struct utsname un;
+    return m_strdup(uname(&un) < 0 ? "Unix" : un.sysname);
 }
 
-@type bool = {
-    .kind = 'b';
-    .ctype = unsigned : 1;
-};
+static char *madmutt_init_hostname(void)
+{
+    char buffer[STRING];
 
-@type string_t = {
-    .kind  = 's';
-    .ctype = char *;
-    .dtor  = p_delete($$);
-    .ctor  = m_strdup($$);
-};
+    if (getdnsdomainname(buffer, sizeof(buffer)) < 0)
+        return m_strdup("@");
 
-@type path_t = {
-    .push  = luaM_path_post($$);
-    .kind  = 's';
-    .ctype = char *;
-    .dtor  = p_delete($$);
-    .ctor  = m_strdup($$);
-};
+    if (*buffer != '@') {
+        int len   = m_strlen(buffer) + m_strlen(mod_core.shorthost) + 2;
+        char *res = p_new(char, len);
+        snprintf(res, len, "%s.%s", NONULL(mod_core.shorthost), buffer);
+        return res;
+    }
+
+    return m_strdup(NONULL(mod_core.shorthost));
+}
+
+static void madmutt_update_cachedir(const char *dir)
+{
+    static char *cachedir = NULL;
+    char path[_POSIX_PATH_MAX];
+    char buf[HUGE_STRING];
+    struct stat st;
+
+    _mutt_expand_path(path, sizeof(path), dir, 0);
+    if (lstat(path, &st) || !S_ISDIR(st.st_mode)) {
+        snprintf(buf, sizeof(buf), _("Directory %s not exist. Create it?"),
+                 dir);
+        if (mutt_yesorno(buf, M_YES) == M_YES)
+            mkdir(path, 0750);
+    }
+
+    if (lstat(path, &st) || !S_ISDIR(st.st_mode)) {
+        mutt_error(_("Cache directory not created!"));
+        return;
+    }
+    if (st.st_mode & 0027) {
+        snprintf(buf, sizeof(buf),
+                 _("Directory %s is unsafe, do you want to use it ?"), dir);
+        if (mutt_yesorno(buf, M_YES) != M_YES)
+            return;
+    }
+
+    m_strreplace(&cachedir, path);
+    mod_core.cachedir = cachedir;
+}
 
-@type quadopt_t = {
-    .kind  = 'i';
-    .check = luaM_checkquadopt($L, $$);
-    .ctype = unsigned : 2;
-};
 
-#if defined(HAVE_QDBM)
-#  define HCACHE_BACKEND "qdbm"
+#if defined(HAVE_TOKYOCABINET)
+#  define HCACHE_BACKEND  "tokyocabinet"
+#elif defined(HAVE_QDBM)
+#  define HCACHE_BACKEND  "qdbm"
 #elif defined(HAVE_GDBM)
-#  define HCACHE_BACKEND "gdbm"
+#  define HCACHE_BACKEND  "gdbm"
 #elif defined(HAVE_DB4)
-#  define HCACHE_BACKEND "db4"
+#  define HCACHE_BACKEND  "db4"
 #else
-#  define HCACHE_BACKEND "unknown"
+#  define HCACHE_BACKEND  NULL
 #endif
 
-@package MCore {
+static void mod_core_init2(void)
+{
+    madmutt_update_cachedir("~/.cache/madmutt");
+}
+#define mod_core_init()  do { (mod_core_init)(); mod_core_init2(); } while (0)
+
+@package mod_core {
+    /*
+     ** .pp
+     ** \fIThis is a read-only system property and specifies madmutt's
+     ** version string.\fP
+     */
     const string_t version    = VERSION;
+    /*
+     ** .pp
+     ** \fIThis is a read-only system property and specifies madmutt's
+     ** subversion revision string.\fP
+     */
     const string_t sysconfdir = SYSCONFDIR;
+    /*
+     ** .pp
+     ** \fIThis is a read-only system property and specifies the
+     ** directory containing the madmutt binary.\fP
+     */
     const string_t bindir     = BINDIR;
+    /*
+     ** .pp
+     ** \fIThis is a read-only system property and specifies the
+     ** directory containing the madmutt documentation.\fP
+     */
     const string_t docdir     = PKGDOCDIR;
+    /*
+     ** .pp
+     ** \fIThis is a read-only system property and specifies the
+     ** header chaching's database backend.\fP
+     */
     const string_t hcache_backend = HCACHE_BACKEND;
 
-    path_t dotlock  = m_strdup(BINDIR "/mutt_dotlock");
-    path_t editor   = m_strdup(getenv("VISUAL") ?: getenv("EDITOR") ?: "vi");
-    path_t shell    = madmutt_init_shell();
-    path_t username = madmutt_init_username();
-    path_t homedir  = madmutt_init_homedir();
-    path_t tmpdir   = m_strdup(getenv("TMPDIR") ?: "/tmp");
+    /*
+     ** .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.
+     */
+    path_t editor         = m_strdup(getenv("VISUAL") ?: getenv("EDITOR") ?: "vi");
+    /*
+     ** .pp
+     ** Command to use when spawning a subshell.  By default, the user's login
+     ** shell from \fT/etc/passwd\fP is used.
+     */
+    path_t shell          = madmutt_init_shell();
+
+    /*
+     ** .pp
+     ** This specifies the operating system name for the \fTUser-Agent:\fP header field. If
+     ** this is \fIunset\fP, it will be set to the operating system name that \fTuname(2)\fP
+     ** returns. If \fTuname(2)\fP fails, ``UNIX'' will be used.
+     ** .pp
+     ** It may, for example, look as: ``\fTMadmutt 1.5.9i (Linux)\fP''.
+     */
+    string_t operating_system = madmutt_init_os();
+
+    path_t username       = madmutt_init_username();
+    path_t homedir        = madmutt_init_homedir();
+
+    /*
+     ** .pp
+     ** Specifies the hostname to use after the ``\fT@\fP'' in local e-mail
+     ** addresses and during generation of \fTMessage-ID:\fP headers.
+     ** .pp
+     ** Please be sure to really know what you are doing when changing this variable
+     ** to configure a custom domain part of Message-IDs.
+     */
+    string_t shorthost    = madmutt_init_shorthost();
+    string_t hostname     = madmutt_init_hostname();
+
+    /*
+     ** .pp
+     ** This variable allows you to specify where Madmutt will place its
+     ** temporary files needed for displaying and composing messages.  If
+     ** this variable is not set, the environment variable \fT$$$TMPDIR\fP is
+     ** used.  If \fT$$$TMPDIR\fP is not set then "\fT/tmp\fP" is used.
+     */
+    path_t tmpdir         = m_strdup(getenv("TMPDIR") ?: "/tmp");
+    /*
+     ** .pp
+     ** A regular expression used by Madmutt to parse the GECOS field of a password
+     ** entry when expanding the alias.  By default the regular expression is set
+     ** to ``\fT^[^,]*\fP'' which will return the string up to the first ``\fT,\fP'' encountered.
+     ** If the GECOS field contains a string like "lastname, firstname" then you
+     ** should do: \fTset gecos_mask=".*"\fP.
+     ** .pp
+     ** This can be useful if you see the following behavior: you address a e-mail
+     ** to user ID stevef whose full name is Steve Franklin.  If Madmutt expands
+     ** stevef to ``Franklin'' stevef@foo.bar then you should set the gecos_mask to
+     ** a regular expression that will match the whole name so Madmutt will expand
+     ** ``Franklin'' to ``Franklin, Steve''.
+     */
+    rx_t   gecos_mask     = luaM_rxnew("^[^,]*");
+
+    /*
+     ** .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.
+     */
+    quadopt_t quit        = M_YES;
+    /*
+     ** .pp
+     ** When this variable is \fIset\fP, Madmutt will beep when an error occurs.
+     */
+    bool      beep        = 1;
+    /*
+     ** .pp
+     ** When this variable is \fIset\fP, Madmutt will beep whenever it prints a message
+     ** notifying you of new mail.  This is independent of the setting of the
+     ** ``$$beep'' variable.
+     */
+    bool      beep_new    = 0;
+
+    /*
+     ** .pp
+     ** When \fIset\fP, Madmutt will qualify all local addresses (ones without the
+     ** @host portion) with the value of ``$$hostname''.  If \fIunset\fP, no
+     ** addresses will be qualified.
+     */
+    bool      use_domain  = 1;
+
+    /*
+     ** .pp
+     ** \fIThis is a read-only system property and, at runtime,
+     ** specifies the current working directory of the madmutt
+     ** binary.\fP
+     */
+    const string_t pwd(void) {
+        char path[_POSIX_PATH_MAX];
+        getcwd(path, sizeof(path));
+        RETURN(path);
+    };
 
-    quadopt_t quit     = M_YES;
-    bool      beep     = 1;
-    bool      beep_new = 0;
+    /*
+     ** .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
+     */
+    const string_t folder_path(void) {
+        RETURN(CurrentFolder);
+    };
 
-    const string_t pwd(void) = madmutt_pwd();
-} MCore;
+    /*
+     ** .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.
+     */
+    const string_t folder_name(void) {
+        const char *p;
+
+        if (!m_strisempty(Maildir)
+        &&  m_strstart(CurrentFolder, Maildir, &p) && *p) {
+            while (*p == '/')
+                p++;
+            RETURN(p);
+        } else {
+            p = strchr(CurrentFolder ?: "", '/');
+            RETURN(p ? p + 1 : (CurrentFolder ?: ""));
+        }
+    };
+
+
+    const string_t cachedir = NULL;
+    void setcachedir(const string_t path) {
+        madmutt_update_cachedir(path);
+        RETURN();
+    };
+};
 
 @package MTransport {
+    /*
+     ** .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.
+     */
     path_t   sendmail = m_strdup(SENDMAIL " -eom -oi");
 
+    /*
+     ** .pp
+     ** \fBNote:\fP you should not enable this unless you are using Sendmail
+     ** 8.8.x or greater.
+     ** .pp
+     ** This variable sets the request for when notification is returned.  The
+     ** string consists of a comma separated list (no spaces!) of one or more
+     ** of the following: \fInever\fP, to never request notification,
+     ** \fIfailure\fP, to request notification on transmission failure,
+     ** \fIdelay\fP, to be notified of message delays, \fIsuccess\fP, to be
+     ** notified of successful transmission.
+     ** .pp
+     ** Example: \fTset dsn_notify="failure,delay"\fP
+     */
+    /* TODO: check it's NULL, hdrs or full */
     string_t dsn_notify = NULL;
+
+    /*
+     ** .pp
+     ** \fBNote:\fP you should not enable this unless you are using Sendmail
+     ** 8.8.x or greater.
+     ** .pp
+     ** This variable controls how much of your message is returned in DSN
+     ** messages.  It may be set to either \fIhdrs\fP to return just the
+     ** message header, or \fIfull\fP to return the full message.
+     ** .pp
+     ** Example: \fTset dsn_return=hdrs\fP
+     */
+    /* TODO: check it's never, delay, failure, success with ',' */
     string_t dsn_return = NULL;
-} MTransport;
+
+    /*
+     ** .pp
+     ** Specifies the number of seconds to wait for the ``$$sendmail'' process
+     ** to finish before giving up and putting delivery in the background.
+     ** .pp
+     ** Madmutt interprets the value of this variable as follows:
+     ** .dl
+     ** .dt >0 .dd number of seconds to wait for sendmail to finish before continuing
+     ** .dt 0  .dd wait forever for sendmail to finish
+     ** .dt <0 .dd always put sendmail in the background without waiting
+     ** .de
+     ** .pp
+     ** Note that if you specify a value other than 0, the output of the child
+     ** process will be put in a temporary file.  If there is some error, you
+     ** will be informed as to where to find the output.
+     */
+    int sendmail_wait = 0;
+    /*
+     ** .pp
+     ** \fBWarning:\fP do not set this variable unless you are using a version
+     ** of sendmail which supports the \fT-B8BITMIME\fP flag (such as sendmail
+     ** 8.8.x).
+     ** Otherwise you may not be able to send mail.
+     ** .pp
+     ** When \fIset\fP, Madmutt will either invoke ``$$sendmail'' with the \fT-B8BITMIME\fP
+     ** flag when sending 8-bit messages to enable ESMTP negotiation.
+     */
+    bool use_8bitmime = 0;
+
+    /*
+     ** .pp
+     ** When \fIset\fP, Madmutt will use ``$$envelope_from_address'' as the
+     ** \fIenvelope\fP sender if that is set, otherwise it will attempt to
+     ** derive it from the "From:" header.
+     **
+     ** .pp
+     ** \fBNote:\fP This information is passed to sendmail command using the
+     ** "-f" command line switch.
+     */
+    bool use_envelope_from = 0;
+
+    /*
+     ** .pp
+     ** Manually sets the \fIenvelope\fP sender for outgoing messages.
+     ** This value is ignored if ``$$use_envelope_from'' is unset.
+     */
+    address_t envelope_from_address = NULL;
+};
 
 /* vim:set ft=c: */