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