1 /* Lua interface (scripting engine) */
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #include <setjmp.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14
15 #include <lua.h>
16 #include <lualib.h>
17
18 #include "elinks.h"
19
20 #include "bfu/dialog.h"
21 #include "cache/cache.h"
22 #include "config/home.h"
23 #include "config/kbdbind.h"
24 #include "config/options.h"
25 #include "config/opttypes.h"
26 #include "document/document.h"
27 #include "document/renderer.h"
28 #include "document/view.h"
29 #include "intl/charsets.h"
30 #include "intl/gettext/libintl.h"
31 #include "main/event.h"
32 #include "main/module.h"
33 #include "osdep/signals.h"
34 #include "protocol/uri.h"
35 #include "scripting/lua/core.h"
36 #include "session/location.h"
37 #include "session/session.h"
38 #include "session/task.h"
39 #include "terminal/terminal.h"
40 #include "util/color.h"
41 #include "util/conv.h"
42 #include "util/file.h"
43 #include "util/memory.h"
44 #include "util/string.h"
45 #include "viewer/dump/dump.h"
46 #include "viewer/text/view.h"
47 #include "viewer/text/vs.h"
48
49 #define LUA_HOOKS_FILENAME "hooks.lua"
50
51
52 lua_State *lua_state;
53
54 static struct session *lua_ses;
55 static struct terminal *errterm;
56 static sigjmp_buf errjmp;
57
58 #define L lua_state
59 #define LS lua_State *S
60
61 static void handle_standard_lua_returns(unsigned char *from);
62 static void handle_ref(LS, struct session *ses, int func_ref,
63 unsigned char *from, int num_args, int unref);
64
65
66 /*
67 * Functions exported to the lua_State.
68 */
69
70 static int
l_alert(LS)71 l_alert(LS)
72 {
73 unsigned char *msg = (unsigned char *) lua_tostring(S, 1);
74
75 /* Don't crash if a script calls e.g. error(nil) or error(error). */
76 if (msg == NULL)
77 msg = "(cannot convert the error message to a string)";
78
79 alert_lua_error(msg);
80 return 0;
81 }
82
83 static int
l_current_url(LS)84 l_current_url(LS)
85 {
86 if (lua_ses && have_location(lua_ses)) {
87 struct view_state *vs = &cur_loc(lua_ses)->vs;
88 unsigned char *url = get_uri_string(vs->uri, URI_ORIGINAL);
89
90 if (url) {
91 lua_pushstring(S, url);
92 mem_free(url);
93 return 1;
94 }
95 }
96
97 lua_pushnil(S);
98 return 1;
99 }
100
101 static int
l_current_link(LS)102 l_current_link(LS)
103 {
104 struct link *link = get_current_session_link(lua_ses);
105
106 if (link) {
107 lua_pushstring(S, link->where);
108 } else {
109 lua_pushnil(S);
110 }
111
112 return 1;
113 }
114
115 static int
l_current_title(LS)116 l_current_title(LS)
117 {
118 struct document_view *doc_view = current_frame(lua_ses);
119
120 if (doc_view && doc_view->document->title) {
121 unsigned char *clean_title = stracpy(doc_view->document->title);
122
123 if (clean_title) {
124 sanitize_title(clean_title);
125
126 lua_pushstring(S, clean_title);
127 mem_free(clean_title);
128 return 1;
129 }
130 }
131
132 lua_pushnil(S);
133 return 1;
134 }
135
136 static int
l_current_document(LS)137 l_current_document(LS)
138 {
139 if (lua_ses) {
140 struct cache_entry *cached = find_in_cache(cur_loc(lua_ses)->vs.uri);
141 struct fragment *f = cached ? cached->frag.next : NULL;
142
143 if (f && f->length) {
144 lua_pushlstring(S, f->data, f->length);
145 return 1;
146 }
147 }
148
149 lua_pushnil(S);
150 return 1;
151 }
152
153 /* XXX: This function is mostly copied from `dump_to_file'. */
154 static int
l_current_document_formatted(LS)155 l_current_document_formatted(LS)
156 {
157 struct document_view *doc_view;
158 struct string buffer;
159 int width, old_width = 0;
160
161 if (lua_gettop(S) == 0) width = -1;
162 else if (!lua_isnumber(S, 1)) goto lua_error;
163 else if ((width = lua_tonumber(S, 1)) <= 0) goto lua_error;
164
165 if (!lua_ses || !(doc_view = current_frame(lua_ses))) goto lua_error;
166 if (width > 0) {
167 old_width = lua_ses->tab->term->width;
168 lua_ses->tab->term->width = width;
169 render_document_frames(lua_ses, 0);
170 }
171
172 if (init_string(&buffer)) {
173 add_document_to_string(&buffer, doc_view->document);
174 lua_pushlstring(S, buffer.source, buffer.length);
175 done_string(&buffer);
176 }
177
178 if (width > 0) {
179 lua_ses->tab->term->width = old_width;
180 render_document_frames(lua_ses, 0);
181 }
182 return 1;
183
184 lua_error:
185 lua_pushnil(S);
186 return 1;
187 }
188
189 static int
l_pipe_read(LS)190 l_pipe_read(LS)
191 {
192 FILE *fp;
193 unsigned char *s = NULL;
194 size_t len = 0;
195
196 if (!lua_isstring(S, 1)) goto lua_error;
197
198 fp = popen(lua_tostring(S, 1), "r");
199 if (!fp) goto lua_error;
200
201 while (!feof(fp)) {
202 unsigned char buf[1024];
203 size_t l = fread(buf, 1, sizeof(buf), fp);
204
205 if (l > 0) {
206 unsigned char *news = mem_realloc(s, len + l);
207
208 if (!news) goto lua_error;
209 s = news;
210 memcpy(s + len, buf, l);
211 len += l;
212
213 } else if (l < 0) {
214 goto lua_error;
215 }
216 }
217 pclose(fp);
218
219 lua_pushlstring(S, s, len);
220 mem_free_if(s);
221 return 1;
222
223 lua_error:
224 mem_free_if(s);
225 lua_pushnil(S);
226 return 1;
227 }
228
229 static int
l_execute(LS)230 l_execute(LS)
231 {
232 if (lua_isstring(S, 1)) {
233 exec_on_terminal(lua_ses->tab->term, (unsigned char *) lua_tostring(S, 1), "", 0);
234 lua_pushnumber(S, 0);
235 return 1;
236 }
237
238 lua_pushnil(L);
239 return 1;
240 }
241
242 static int
l_tmpname(LS)243 l_tmpname(LS)
244 {
245 unsigned char *fn = tempnam(NULL, "elinks");
246
247 if (fn) {
248 lua_pushstring(S, fn);
249 free(fn);
250 return 1;
251 }
252
253 alert_lua_error("Error generating temporary file name");
254 lua_pushnil(S);
255 return 1;
256 }
257
258 /*
259 * Helper to run Lua functions bound to keystrokes.
260 */
261
262 static enum evhook_status
run_lua_func(va_list ap,void * data)263 run_lua_func(va_list ap, void *data)
264 {
265 struct session *ses = va_arg(ap, struct session *);
266 int func_ref = (long) data;
267
268 if (func_ref == LUA_NOREF) {
269 alert_lua_error("key bound to nothing (internal error)");
270 return EVENT_HOOK_STATUS_NEXT;
271 }
272
273 handle_ref(L, ses, func_ref, "keyboard function", 0, 0);
274
275 return EVENT_HOOK_STATUS_NEXT;
276 }
277
278 static int
l_bind_key(LS)279 l_bind_key(LS)
280 {
281 int ref;
282 int event_id;
283 unsigned char *err = NULL;
284 struct string event_name = NULL_STRING;
285
286 if (!lua_isstring(S, 1) || !lua_isstring(S, 2)
287 || !lua_isfunction(S, 3)) {
288 alert_lua_error("bad arguments to bind_key");
289 goto lua_error;
290 }
291
292 if (!init_string(&event_name)) goto lua_error;
293
294 lua_pushvalue(S, 3);
295 ref = luaL_ref(S, LUA_REGISTRYINDEX);
296 add_format_to_string(&event_name, "lua-run-func %i", ref);
297
298 event_id = bind_key_to_event_name((unsigned char *) lua_tostring(S, 1),
299 (unsigned char *) lua_tostring(S, 2),
300 event_name.source, &err);
301 done_string(&event_name);
302
303 if (!err) {
304 event_id = register_event_hook(event_id, run_lua_func, 0,
305 (void *) (long) ref);
306
307 if (event_id == EVENT_NONE)
308 err = gettext("Error registering event hook");
309 }
310
311 if (err) {
312 luaL_unref(S, LUA_REGISTRYINDEX, ref);
313 alert_lua_error2("error in bind_key: ", err);
314 goto lua_error;
315 }
316
317 lua_pushnumber(S, 1);
318 return 1;
319
320 lua_error:
321 lua_pushnil(S);
322 return 1;
323 }
324
325
326 /* Begin very hackish bit for bookmark editing dialog. */
327 /* XXX: Add history and generalise. */
328
329 struct lua_dlg_data {
330 lua_State *state;
331 unsigned char cat[MAX_STR_LEN];
332 unsigned char name[MAX_STR_LEN];
333 unsigned char url[MAX_STR_LEN];
334 int func_ref;
335 };
336
337 static void
dialog_run_lua(void * data_)338 dialog_run_lua(void *data_)
339 {
340 struct lua_dlg_data *data = data_;
341 lua_State *s = data->state;
342
343 lua_pushstring(s, data->cat);
344 lua_pushstring(s, data->name);
345 lua_pushstring(s, data->url);
346 handle_ref(s, lua_ses, data->func_ref, "post dialog function", 3, 1);
347 }
348
349 static int
l_edit_bookmark_dialog(LS)350 l_edit_bookmark_dialog(LS)
351 {
352 struct terminal *term = lua_ses->tab->term;
353 struct dialog *dlg;
354 struct lua_dlg_data *data;
355
356 if (!lua_isstring(S, 1) || !lua_isstring(S, 2)
357 || !lua_isstring(S, 3) || !lua_isfunction(S, 4)) {
358 lua_pushnil(S);
359 return 1;
360 }
361
362 #define L_EDIT_BMK_WIDGETS_COUNT 5
363 dlg = calloc_dialog(L_EDIT_BMK_WIDGETS_COUNT, sizeof(*data));
364 if (!dlg) return 0;
365
366 data = (struct lua_dlg_data *) get_dialog_offset(dlg, L_EDIT_BMK_WIDGETS_COUNT);
367 data->state = S;
368 safe_strncpy(data->cat, (unsigned char *) lua_tostring(S, 1),
369 MAX_STR_LEN-1);
370 safe_strncpy(data->name, (unsigned char *) lua_tostring(S, 2),
371 MAX_STR_LEN-1);
372 safe_strncpy(data->url, (unsigned char *) lua_tostring(S, 3),
373 MAX_STR_LEN-1);
374 lua_pushvalue(S, 4);
375 data->func_ref = luaL_ref(S, LUA_REGISTRYINDEX);
376
377 dlg->title = _("Edit bookmark", term);
378 dlg->layouter = generic_dialog_layouter;
379 dlg->layout.maximize_width = 1;
380
381 add_dlg_field(dlg, _("Name", term), 0, 0, NULL, MAX_STR_LEN, data->cat, NULL);
382 add_dlg_field(dlg, _("Name", term), 0, 0, NULL, MAX_STR_LEN, data->name, NULL);
383 add_dlg_field(dlg, _("URL", term), 0, 0, NULL, MAX_STR_LEN, data->url, NULL);
384
385 add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, dialog_run_lua, data);
386 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
387
388 add_dlg_end(dlg, L_EDIT_BMK_WIDGETS_COUNT);
389
390 do_dialog(term, dlg, getml(dlg, NULL));
391
392 lua_pushnumber(S, 1);
393 return 1;
394 }
395
396 /* End very hackish bit. */
397
398
399 /* Begin hackish bit for half-generalised dialog. */
400 /* XXX: Add history and custom labels. */
401
402 #define XDIALOG_MAX_FIELDS 5
403
404 struct lua_xdialog_data {
405 lua_State *state;
406 int func_ref;
407 int nfields;
408 unsigned char fields[XDIALOG_MAX_FIELDS][MAX_STR_LEN];
409 };
410
411 static void
xdialog_run_lua(void * data_)412 xdialog_run_lua(void *data_)
413 {
414 struct lua_xdialog_data *data = data_;
415 lua_State *s = data->state;
416 int i;
417
418 for (i = 0; i < data->nfields; i++) lua_pushstring(s, data->fields[i]);
419 handle_ref(s, lua_ses, data->func_ref, "post xdialog function",
420 data->nfields, 1);
421 }
422
423 static int
l_xdialog(LS)424 l_xdialog(LS)
425 {
426 struct terminal *term;
427 struct dialog *dlg;
428 struct lua_xdialog_data *data;
429 int nargs, nfields, nitems;
430 int i = 0;
431
432 if (!lua_ses) return 0;
433
434 term = lua_ses->tab->term;
435
436 nargs = lua_gettop(S);
437 nfields = nargs - 1;
438 nitems = nfields + 2;
439
440 if ((nfields < 1) || (nfields > XDIALOG_MAX_FIELDS)) goto lua_error;
441 for (i = 1; i < nargs; i++) if (!lua_isstring(S, i)) goto lua_error;
442 if (!lua_isfunction(S, nargs)) goto lua_error;
443
444 dlg = calloc_dialog(nitems, sizeof(*data));
445 if (!dlg) return 0;
446
447 data = (struct lua_xdialog_data *) get_dialog_offset(dlg, nitems);
448 data->state = S;
449 data->nfields = nfields;
450 for (i = 0; i < nfields; i++)
451 safe_strncpy(data->fields[i],
452 (unsigned char *) lua_tostring(S, i+1),
453 MAX_STR_LEN-1);
454 lua_pushvalue(S, nargs);
455 data->func_ref = luaL_ref(S, LUA_REGISTRYINDEX);
456
457 dlg->title = _("User dialog", term);
458 dlg->layouter = generic_dialog_layouter;
459 dlg->layout.maximize_width = 1;
460
461 for (i = 0; i < nfields; i++)
462 add_dlg_field(dlg, _("Name", term), 0, 0, NULL, MAX_STR_LEN,
463 data->fields[i], NULL);
464
465 add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, xdialog_run_lua, data);
466 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
467
468 add_dlg_end(dlg, nitems);
469
470 do_dialog(term, dlg, getml(dlg, NULL));
471
472 lua_pushnumber(S, 1);
473 return 1;
474
475 lua_error:
476 lua_pushnil(S);
477 return 1;
478 }
479
480 /* End xdialog bit. */
481
482 /* Set/get option */
483
484 static int
l_set_option(LS)485 l_set_option(LS)
486 {
487 int nargs;
488 struct option *opt, *current;
489 const char *name;
490
491 nargs = lua_gettop(S);
492 if (nargs != 2)
493 goto lua_error;
494
495 /* Get option record */
496 name = lua_tostring(S, 1);
497 opt = get_opt_rec(config_options, (unsigned char *) name);
498 if (opt == NULL)
499 goto lua_error;
500
501 /* Set option */
502 switch (opt->type) {
503 case OPT_BOOL:
504 {
505 /* option_types[OPT_BOOL].set expects a long even though it
506 * saves the value to opt->value.number, which is an int. */
507 long value = lua_toboolean(S, 2);
508
509 option_types[opt->type].set(opt, (unsigned char *) (&value));
510 break;
511 }
512 case OPT_INT:
513 case OPT_LONG:
514 {
515 /* option_types[OPT_INT].set expects a long even though it
516 * saves the value to opt->value.number, which is an int.
517 * option_types[OPT_LONG].set of course wants a long too. */
518 long value = lua_tonumber(S, 2);
519
520 option_types[opt->type].set(opt, (unsigned char *) (&value));
521 break;
522 }
523 case OPT_STRING:
524 case OPT_CODEPAGE:
525 case OPT_LANGUAGE:
526 case OPT_COLOR:
527 option_types[opt->type].set(opt, (unsigned char *) lua_tostring(S, 2));
528 break;
529 default:
530 goto lua_error;
531 }
532
533 opt->flags |= OPT_TOUCHED;
534
535 /* Call hook */
536 current = opt;
537 call_change_hooks(lua_ses, current, opt);
538 return 1;
539
540 lua_error:
541 lua_pushnil(S);
542 return 1;
543 }
544
545 static int
l_get_option(LS)546 l_get_option(LS)
547 {
548 int nargs;
549 struct option *opt;
550 const char *name;
551
552 /* Get option record */
553 nargs = lua_gettop(S);
554 if (nargs != 1)
555 goto lua_error;
556 name = lua_tostring(S, 1);
557 opt = get_opt_rec(config_options, (unsigned char *) name);
558 if (opt == NULL)
559 goto lua_error;
560
561 /* Convert to an appropriate Lua type */
562 switch (opt->type) {
563 case OPT_BOOL:
564 lua_pushboolean(S, opt->value.number);
565 break;
566 case OPT_INT:
567 lua_pushnumber(S, opt->value.number);
568 break;
569 case OPT_LONG:
570 lua_pushnumber(S, opt->value.big_number);
571 break;
572 case OPT_STRING:
573 lua_pushstring(S, opt->value.string);
574 break;
575 case OPT_CODEPAGE:
576 {
577 unsigned char *cp_name;
578
579 cp_name = get_cp_mime_name(opt->value.number);
580 lua_pushstring(S, cp_name);
581 break;
582 }
583 case OPT_LANGUAGE:
584 {
585 unsigned char *lang;
586
587 #ifdef ENABLE_NLS
588 lang = language_to_name(current_language);
589 #else
590 lang = "System";
591 #endif
592 lua_pushstring(S, lang);
593 break;
594 }
595 case OPT_COLOR:
596 {
597 color_T color;
598 unsigned char hexcolor[8];
599 unsigned char *strcolor;
600
601 color = opt->value.color;
602 strcolor = get_color_string(color, hexcolor);
603 lua_pushstring(S, strcolor);
604 break;
605 }
606 case OPT_COMMAND:
607 default:
608 goto lua_error;
609 }
610
611 return 1;
612
613 lua_error:
614 lua_pushnil(S);
615 return 1;
616 }
617
618 /* End of set/get option */
619
620 int
eval_function(LS,int num_args,int num_results)621 eval_function(LS, int num_args, int num_results)
622 {
623 int err;
624
625 err = lua_pcall(S, num_args, num_results, 0);
626 if (err) {
627 alert_lua_error((unsigned char *) lua_tostring(L, -1));
628 lua_pop(L, 1);
629 }
630
631 return err;
632 }
633
634 /* Initialisation */
635
636 static void
do_hooks_file(LS,unsigned char * prefix,unsigned char * filename)637 do_hooks_file(LS, unsigned char *prefix, unsigned char *filename)
638 {
639 unsigned char *file = straconcat(prefix, "/", filename, NULL);
640
641 if (!file) return;
642
643 /* Test file existence to avoid Lua error reporting (under version 5.x)
644 * Fixes debian bug #231760 ('dbug 231760' using URI rewrite) */
645 if (file_can_read(file)) {
646 int oldtop = lua_gettop(S);
647
648 if (lua_dofile(S, file) != 0)
649 sleep(3); /* Let some time to see error messages. */
650 lua_settop(S, oldtop);
651 }
652
653 mem_free(file);
654 }
655
656 void
init_lua(struct module * module)657 init_lua(struct module *module)
658 {
659 L = lua_open();
660
661 luaopen_base(L);
662 luaopen_table(L);
663 luaopen_io(L);
664 luaopen_string(L);
665 luaopen_math(L);
666
667 lua_register(L, LUA_ALERT, l_alert);
668 lua_register(L, "current_url", l_current_url);
669 lua_register(L, "current_link", l_current_link);
670 lua_register(L, "current_title", l_current_title);
671 lua_register(L, "current_document", l_current_document);
672 lua_register(L, "current_document_formatted", l_current_document_formatted);
673 lua_register(L, "pipe_read", l_pipe_read);
674 lua_register(L, "execute", l_execute);
675 lua_register(L, "tmpname", l_tmpname);
676 lua_register(L, "bind_key", l_bind_key);
677 lua_register(L, "edit_bookmark_dialog", l_edit_bookmark_dialog);
678 lua_register(L, "xdialog", l_xdialog);
679 lua_register(L, "set_option", l_set_option);
680 lua_register(L, "get_option", l_get_option);
681
682 lua_pushstring(L, elinks_home ? elinks_home
683 : (unsigned char *) CONFDIR);
684 lua_setglobal(L, "elinks_home");
685
686 do_hooks_file(L, CONFDIR, LUA_HOOKS_FILENAME);
687 if (elinks_home) do_hooks_file(L, elinks_home, LUA_HOOKS_FILENAME);
688 }
689
690 static void free_lua_console_history_entries(void);
691
692 void
cleanup_lua(struct module * module)693 cleanup_lua(struct module *module)
694 {
695 free_lua_console_history_entries();
696 lua_close(L);
697 }
698
699 /* Attempt to handle infinite loops by trapping SIGINT. If we get a
700 * SIGINT, we longjump to where prepare_lua was called. finish_lua()
701 * disables the trapping. */
702
703 static void
handle_sigint(void * data)704 handle_sigint(void *data)
705 {
706 finish_lua();
707 siglongjmp(errjmp, -1);
708 }
709
710 int
prepare_lua(struct session * ses)711 prepare_lua(struct session *ses)
712 {
713 lua_ses = ses;
714 errterm = lua_ses ? lua_ses->tab->term : NULL;
715 /* XXX this uses the wrong term, I think */
716 install_signal_handler(SIGINT, (void (*)(void *)) handle_sigint, NULL, 1);
717
718 return sigsetjmp(errjmp, 1);
719 }
720
721 void
finish_lua(void)722 finish_lua(void)
723 {
724 /* XXX should save previous handler instead of assuming this one */
725 install_signal_handler(SIGINT, (void (*)(void *)) sig_ctrl_c, errterm, 0);
726 }
727
728
729 /* Error reporting. */
730
731 void
alert_lua_error(unsigned char * msg)732 alert_lua_error(unsigned char *msg)
733 {
734 if (errterm) {
735 info_box(errterm, MSGBOX_NO_TEXT_INTL | MSGBOX_FREE_TEXT,
736 N_("Lua Error"), ALIGN_LEFT,
737 stracpy(msg));
738 return;
739 }
740
741 usrerror("Lua: %s", msg);
742 sleep(3);
743 }
744
745 void
alert_lua_error2(unsigned char * msg,unsigned char * msg2)746 alert_lua_error2(unsigned char *msg, unsigned char *msg2)
747 {
748 unsigned char *tmp = stracpy(msg);
749
750 if (!tmp) return;
751 add_to_strn(&tmp, msg2);
752 alert_lua_error(tmp);
753 mem_free(tmp);
754 }
755
756
757 /* The following stuff is to handle the return values of
758 * lua_console_hook and keystroke functions, and also the xdialog
759 * function. It expects two values on top of the stack. */
760
761 static void
handle_ret_eval(struct session * ses)762 handle_ret_eval(struct session *ses)
763 {
764 const unsigned char *expr = lua_tostring(L, -1);
765
766 if (expr) {
767 int oldtop = lua_gettop(L);
768
769 if (prepare_lua(ses) == 0) {
770 lua_dostring(L, expr);
771 lua_settop(L, oldtop);
772 finish_lua();
773 }
774 return;
775 }
776
777 alert_lua_error("bad argument for eval");
778 }
779
780 static void
handle_ret_run(struct session * ses)781 handle_ret_run(struct session *ses)
782 {
783 unsigned char *cmd = (unsigned char *) lua_tostring(L, -1);
784
785 if (cmd) {
786 exec_on_terminal(ses->tab->term, cmd, "", 1);
787 return;
788 }
789
790 alert_lua_error("bad argument for run");
791 }
792
793 static void
handle_ret_goto_url(struct session * ses)794 handle_ret_goto_url(struct session *ses)
795 {
796 unsigned char *url = (unsigned char *) lua_tostring(L, -1);
797
798 if (url) {
799 goto_url_with_hook(ses, url);
800 return;
801 }
802
803 alert_lua_error("bad argument for goto_url");
804 }
805
806 static void
handle_standard_lua_returns(unsigned char * from)807 handle_standard_lua_returns(unsigned char *from)
808 {
809 const unsigned char *act = lua_tostring(L, -2);
810
811 if (act) {
812 if (!strcmp(act, "eval"))
813 handle_ret_eval(lua_ses);
814 else if (!strcmp(act, "run"))
815 handle_ret_run(lua_ses);
816 else if (!strcmp(act, "goto_url"))
817 handle_ret_goto_url(lua_ses);
818 else
819 alert_lua_error2("unrecognised return value from ", from);
820 }
821 else if (!lua_isnil(L, -2))
822 alert_lua_error2("bad return type from ", from);
823
824 lua_pop(L, 2);
825 }
826
827 static void
handle_ref_on_stack(LS,struct session * ses,unsigned char * from,int num_args)828 handle_ref_on_stack(LS, struct session *ses, unsigned char *from, int num_args)
829 {
830 int err;
831
832 if (prepare_lua(ses)) return;
833 err = eval_function(S, num_args, 2);
834 finish_lua();
835
836 if (!err) handle_standard_lua_returns(from);
837 }
838
839 static void
handle_ref(LS,struct session * ses,int func_ref,unsigned char * from,int num_args,int unref)840 handle_ref(LS, struct session *ses, int func_ref, unsigned char *from,
841 int num_args, int unref)
842 {
843 lua_rawgeti(S, LUA_REGISTRYINDEX, func_ref);
844
845 /* The function must be below the arguments on the stack. */
846 if (num_args != 0) lua_insert(S, -(num_args + 1));
847
848 handle_ref_on_stack(S, ses, from, num_args);
849
850 if (unref)
851 luaL_unref(S, LUA_REGISTRYINDEX, func_ref);
852 }
853
854
855 /* Console stuff. */
856
857 static INIT_INPUT_HISTORY(lua_console_history);
858
859 static void
lua_console(struct session * ses,unsigned char * expr)860 lua_console(struct session *ses, unsigned char *expr)
861 {
862 lua_getglobal(L, "lua_console_hook");
863 if (lua_isnil(L, -1)) {
864 lua_pop(L, 1);
865 handle_ret_eval(ses);
866 return;
867 }
868
869 lua_pushstring(L, expr);
870 handle_ref_on_stack(L, ses, "lua_console_hook", 1);
871 }
872
873 /* TODO: Make this a "Scripting console" instead, with a radiobutton below the
874 * inputbox selecting the appropriate scripting backend to use to evaluate the
875 * expression. --pasky */
876
877 enum evhook_status
dialog_lua_console(va_list ap,void * data)878 dialog_lua_console(va_list ap, void *data)
879 {
880 struct session *ses = va_arg(ap, struct session *);
881
882 if (get_cmd_opt_bool("anonymous"))
883 return EVENT_HOOK_STATUS_NEXT;
884
885 input_dialog(ses->tab->term, NULL,
886 N_("Lua Console"), N_("Enter expression"),
887 ses, &lua_console_history,
888 MAX_STR_LEN, "", 0, 0, NULL,
889 (void (*)(void *, unsigned char *)) lua_console, NULL);
890 return EVENT_HOOK_STATUS_NEXT;
891 }
892
893 static void
free_lua_console_history_entries(void)894 free_lua_console_history_entries(void)
895 {
896 free_list(lua_console_history.entries);
897 }
898
899 enum evhook_status
free_lua_console_history(va_list ap,void * data)900 free_lua_console_history(va_list ap, void *data)
901 {
902 free_lua_console_history_entries();
903 return EVENT_HOOK_STATUS_NEXT;
904 }
905