oops
[apps/madmutt.git] / lib-lua / madmutt.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  *
17  *  Copyright © 2007 Pierre Habouzit
18  */
19
20 #include <lib-lib/lib-lib.h>
21
22 #include <sys/types.h>
23 #include <pwd.h>
24
25 #include "lib-lua_priv.h"
26
27 #include "../mutt.h"
28
29 static int madmutt_pwd(lua_State *L)
30 {
31     char path[_POSIX_PATH_MAX];
32     getcwd(path, sizeof(path));
33     lua_pushstring(L, path);
34     return 1;
35 }
36
37 static int madmutt_folder_path(lua_State *L)
38 {
39     lua_pushstring(L, CurrentFolder ?: "");
40     return 1;
41 }
42
43 static int madmutt_folder_name(lua_State *L)
44 {
45     const char *p;
46
47     if (!m_strisempty(Maildir)
48     && m_strstart(CurrentFolder, Maildir, &p) && *p) {
49         while (*p == '/')
50             p++;
51         lua_pushstring(L, p);
52     } else {
53         p = strchr(CurrentFolder ?: "", '/');
54         lua_pushstring(L, p ? p + 1 : (CurrentFolder ?: ""));
55     }
56     return 1;
57 }
58
59 static int madmutt_assign(lua_State *L)
60 {
61     const char *idx = luaL_checkstring(L, 2);
62     const char *val = luaL_checkstring(L, 3);
63     char buf[STRING];
64
65     switch (lua_which_token(idx, -1)) {
66       default:
67         luaL_error(L, "bad subscript to madmutt: %s", val);
68         return 0;
69
70       case LTK_DOTLOCK:
71       case LTK_SENDMAIL:
72       case LTK_SHELL:
73         _mutt_expand_path(buf, sizeof(buf), val, 0);
74         val = buf;
75         break;
76     }
77
78     lua_getmetatable(L, 1);
79     lua_pushstring(L, idx);
80     lua_pushstring(L, val);
81     lua_rawset(L, -3);
82
83     return 0;
84 }
85
86 static const struct luaL_Reg madmutt_module_funcs[] = {
87     {"pwd",         madmutt_pwd},
88     /*
89      ** .pp
90      ** \fIThis is a read-only system property and, at runtime,
91      ** specifies the current working directory of the madmutt
92      ** binary.\fP
93      */
94     {"folder_path", madmutt_folder_path},
95     /*
96      ** .pp
97      ** \fIThis is a read-only system property and, at runtime,
98      ** specifies the full path or URI of the folder currently
99      ** open (if any).\fP
100      */
101     {"folder_name", madmutt_folder_name},
102     /*
103      ** .pp
104      ** \fIThis is a read-only system property and, at runtime,
105      ** specifies the actual name of the folder as far as it could
106      ** be detected.\fP
107      ** .pp
108      ** For detection, $$$folder is first taken into account
109      ** and simply stripped to form the result when a match is found. For
110      ** example, with $$$folder being \fTimap://host\fP and the folder is
111      ** \fTimap://host/INBOX/foo\fP, $$$madmutt_folder_name will be just
112      ** \fTINBOX/foo\fP.)
113      ** .pp
114      ** Second, if the initial portion of a name is not $$$folder,
115      ** the result will be everything after the last ``/''.
116      ** .pp
117      ** Third and last, the result will be just the name if neither
118      ** $$$folder nor a ``/'' were found in the name.
119      */
120
121     {"__newindex",  madmutt_assign},
122     {NULL, NULL}
123 };
124
125 static const struct {
126     const char *key;
127     const char *value;
128 } madmutt_module_vars[] = {
129     { "version",    VERSION },
130     /*
131      ** .pp
132      ** \fIThis is a read-only system property and specifies madmutt's
133      ** version string.\fP
134      */
135     { "sysconfdir", SYSCONFDIR },
136     /*
137      ** .pp
138      ** \fIThis is a read-only system property and specifies madmutt's
139      ** subversion revision string.\fP
140      */
141     { "bindir",     BINDIR },
142     /*
143      ** .pp
144      ** \fIThis is a read-only system property and specifies the
145      ** directory containing the madmutt binary.\fP
146      */
147     { "docdir",     PKGDOCDIR },
148     /*
149      ** .pp
150      ** \fIThis is a read-only system property and specifies the
151      ** directory containing the madmutt documentation.\fP
152      */
153 #ifdef USE_HCACHE
154 #if defined(HAVE_QDBM)
155     { "hcache_backend", "qdbm" },
156 #elif defined(HAVE_GDBM)
157     { "hcache_backend", "gdbm" },
158 #elif defined(HAVE_DB4)
159     { "hcache_backend", "db4" },
160 #else
161     { "hcache_backend", "unknown" },
162 #endif
163     /*
164      ** .pp
165      ** \fIThis is a read-only system property and specifies the
166      ** header chaching's database backend.\fP
167      */
168 #endif
169
170     {"dotlock",     BINDIR "/mutt_dotlock"},
171     /*
172      ** .pp
173      ** Contains the path of the \fTmadmutt_dotlock(1)\fP binary to be used by
174      ** Madmutt.
175      */
176     {"sendmail",    SENDMAIL " -oem -oi"},
177     /*
178      ** .pp
179      ** Specifies the program and arguments used to deliver mail sent by Madmutt.
180      ** Madmutt expects that the specified program interprets additional
181      ** arguments as recipient addresses.
182      */
183 };
184
185 static void madmutt_init_shell(char *buf, ssize_t len)
186 {
187     struct passwd *pw = getpwuid(getuid());
188
189     if (pw) {
190         m_strcpy(buf, len, pw->pw_shell);
191         _mutt_expand_path(buf, len, pw->pw_shell, 0);
192     } else {
193         m_strcpy(buf, len, getenv("SHELL") ?: "/bin/sh");
194     }
195 }
196
197 static const struct {
198     const char *key;
199     void (*fun)(char *buf, ssize_t len);
200 } madmutt_module_vars2[] = {
201     { "shell",          madmutt_init_shell },
202     /*
203      ** .pp
204      ** Command to use when spawning a subshell.  By default, the user's login
205      ** shell from \fT/etc/passwd\fP is used.
206      */
207 };
208
209 int luaopen_madmutt(lua_State *L)
210 {
211     int i;
212
213     lua_newuserdata(L, sizeof(void*));
214     luaL_newmetatable(L, "madmutt.core");
215
216     luaL_openlib(L, NULL, madmutt_module_funcs, 0);
217
218     for (i = 0; i < countof(madmutt_module_vars); i++) {
219         lua_pushstring(L, madmutt_module_vars[i].value);
220         lua_setfield(L, -2, madmutt_module_vars[i].key);
221     }
222
223     for (i = 0; i < countof(madmutt_module_vars2); i++) {
224         char buf[STRING];
225         (madmutt_module_vars2[i].fun)(buf, sizeof(buf));
226         lua_pushstring(L, buf);
227         lua_setfield(L, -2, madmutt_module_vars2[i].key);
228     }
229
230     lua_pushstring(L, "__index");
231     lua_pushvalue(L, -2);
232     lua_settable(L, -3);
233
234     lua_setmetatable(L, -2);
235     lua_setglobal(L, "madmutt");
236
237     return 1;
238 }