Skip to content
Commits on Source (4)
......@@ -5,7 +5,7 @@ include $(DEPTH)Makefile.common
build: duktape.o
duktape.o: duktape.c duktape.h duk_config.h
$(CC) -std=c99 $(CCSEC) duktape.c -c
$(CC) -std=c99 -g $(CCSEC) duktape.c -c
clean:
-rm -f *.o .*.d *.d
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <duktape.h>
#include "js.h"
#include "alias.h"
#include "user.h"
extern struct user * const user;
duk_context *ctx;
struct binding {
int type;
int name_required;
alias **list;
const char *name;
};
const struct binding bindings[] = {
{ K_BIND, 1, &bind_list, "Bind" },
{ K_BIND_ALIAS, 1, &alias_list, "Alias" },
{ K_BIND_RPC, 1, &rpc_list, "RPC bind" },
{ K_BIND_EVENT, 0, &event_list, "Event bind" },
{ K_BIND_ONOFF, 0, &onoff_list, "Check on/off bind" },
{ K_BIND_IPC, 0, &ipc_list, "IPC bind" },
{ K_BIND_FORCE, 0, &force_list, "Force bind" },
{ K_BIND_SHUTDOWN, 0, &shutdown_list, "Shutdown bind" },
{ K_BIND_INPUT, 0, &eventin_list, "Input event bind" },
{ 0, 0, NULL, NULL }
};
static duk_ret_t js_bind(duk_context *cx)
{
const char *bind_name = NULL;
const char *func_name = NULL;
const struct binding *bind;
int bind_type = -1;
if (duk_is_undefined(cx, -2) ||
duk_is_undefined(cx, -3)) {
fprintf(stderr, "mwjs error: bind() expects 2 or 3 arguments\n");
return DUK_RET_SYNTAX_ERROR;
}
if (duk_is_string(cx, -3)) {
bind_name = duk_get_string(cx, -3);
bind_type = K_BIND;
if (!duk_is_undefined(cx, -1)) {
fprintf(stderr, "mwjs error: bind(str, str) expects 2 arguments\n");
return DUK_RET_SYNTAX_ERROR;
}
duk_pop(cx);
} else if (duk_is_number(cx, -3)) {
bind_type = duk_get_int_default(cx, -3, -1);
if (bind_type == K_BIND ||
bind_type == K_BIND_ALIAS ||
bind_type == K_BIND_RPC) {
bind_name = duk_get_string(cx, -2);
} else {
duk_pop(cx);
}
} else {
fprintf(stderr, "mwjs error: first argument to bind() must be a "
"string or bind id\n");
return DUK_RET_SYNTAX_ERROR;
}
func_name = duk_get_string(cx, -1);
if (func_name == NULL) {
fprintf(stderr, "mwjs error: bind(): invalid function name\n");
return DUK_RET_SYNTAX_ERROR;
}
for (bind = &bindings[0]; bind->list != NULL && bind->type != bind_type; bind++);
if (bind->list == NULL) {
fprintf(stderr, "Bind type %d not recognised\n", bind_type);
return DUK_RET_ERROR;
}
if (bind->name_required) {
if (bind_name == NULL || bind_name[0] == '\0') {
fprintf(stderr, "Bind name is empty\n");
return DUK_RET_ERROR;
}
} else {
bind_name = func_name;
func_name = "";
}
if (AddLink(bind->list, bind_name, func_name)) {
fprintf(stderr, "Warning: %s %s already exists.\n",
bind->name, bind_name);
}
return 0;
}
int js_isrunning(void)
{
return 0;
}
int js_exec(char *name, int argc, const char **argvc)
int js_exec(char *name, int argc, const char **argv)
{
int i;
if (duk_get_global_string(ctx, name) && duk_is_function(ctx, -1)) {
for (i = 0; i < argc; i++)
duk_push_string(ctx, argv[i]);
if (duk_pcall(ctx, argc) != DUK_EXEC_SUCCESS) {
if (duk_is_error(ctx, -1)) {
duk_get_prop_string(ctx, -1, "stack");
fprintf(stderr, "mwjs error: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
} else {
fprintf(stderr, "mwjs error: %s\n", duk_safe_to_string(ctx, -1));
}
}
}
duk_pop(ctx);
return 0;
}
/* This limit is fairly arbitrary but a limit is needed and 256K
seems a reasonable file and (temporary) buffer size */
#define MWJS_FILE_MAX_SIZE (256*1024)
int load_jsfile(FILE *f, const char *filename)
{
char buf[MWJS_FILE_MAX_SIZE + 1];
int fd = fileno(f);
struct stat st;
size_t ret;
if (fd == -1) {
fprintf(stderr, "Failed to open '%s': %s\n", filename, strerror(errno));
return 1;
}
if (fstat(fd, &st) != 0) {
fprintf(stderr, "Failed to stat '%s': %s\n", filename, strerror(errno));
return 1;
}
errno = EFBIG;
if (st.st_size > MWJS_FILE_MAX_SIZE) {
fprintf(stderr, "Failed to load '%s': %s\n", filename, strerror(errno));
return 1;
}
ret = fread(buf, sizeof(char), st.st_size, f);
if (ret != st.st_size) {
fprintf(stderr, "Failed to read '%s': %llu bytes read\n",
filename, (unsigned long long)ret);
return 1;
}
buf[MWJS_FILE_MAX_SIZE] = '\0';
if (duk_peval_string(ctx, buf) != 0) {
printf("Failed to execute '%s': %s\n", filename, duk_safe_to_string(ctx, -1));
}
duk_pop(ctx);
return 0;
}
int is_js(char *name)
{
return 0;
int ret = 0;
if (duk_get_global_string(ctx, name) && duk_is_function(ctx, -1))
ret = 1;
duk_pop(ctx);
return ret;
}
void js_stop_execution(void)
......@@ -29,11 +177,59 @@ void js_stop_execution(void)
int stop_js(void)
{
duk_destroy_heap(ctx);
return 0;
}
/* The owning object must be at the top of the stack when calling this */
static void define_func(const char *name, duk_c_function func, int nargs)
{
duk_push_string(ctx, name);
duk_push_c_function(ctx, func, nargs);
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
}
/* The owning object must be at the top of the stack when calling this */
static void define_number(const char *name, duk_double_t num)
{
duk_push_string(ctx, name);
duk_push_number(ctx, num);
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
}
/* The owning object must be at the top of the stack when calling this */
static void define_string(const char *name, const char *value)
{
duk_push_string(ctx, name);
duk_push_string(ctx, value);
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
}
/* The owning object must be at the top of the stack when calling this */
static void define_constants(void)
{
define_number("K_BIND_EVENT", (duk_double_t)K_BIND_EVENT);
define_number("K_BIND_IPC", (duk_double_t)K_BIND_IPC);
define_number("K_BIND_ONOFF", (duk_double_t)K_BIND_ONOFF);
define_number("K_BIND_FORCE", (duk_double_t)K_BIND_FORCE);
define_number("K_BIND_SHUTDOWN", (duk_double_t)K_BIND_SHUTDOWN);
define_number("K_BIND_RPC", (duk_double_t)K_BIND_RPC);
define_number("K_BIND_ALIAS", (duk_double_t)K_BIND_ALIAS);
define_number("K_BIND_INPUT", (duk_double_t)K_BIND_INPUT);
define_number("K_BROADCAST", (duk_double_t)K_BROADCAST);
define_string("whoami", user->record.name);
}
int setup_js(void)
{
ctx = duk_create_heap_default();
if (ctx == NULL)
return -1;
duk_push_global_object(ctx);
define_constants();
define_func("bind", js_bind, 3);
duk_pop(ctx);
return 0;
}
......
......@@ -48,9 +48,6 @@ static JSObject *jsroot = NULL;
int js_interrupted=1;
struct alarm *js_timeout_event=NULL;
enum bindtype { K_BIND=0, K_BIND_EVENT, K_BIND_ONOFF, K_BIND_IPC, K_BIND_FORCE, K_BIND_SHUTDOWN, K_BIND_ALIAS, K_BIND_RPC, K_BIND_INPUT };
#define K_BROADCAST 1
JSClass globclass = {
"milliways", JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_StrictPropertyStub,
......
......@@ -13,4 +13,17 @@ int setup_js(void);
size_t urldata(void *ptr, size_t size, size_t nmemb, void *stream);
size_t headlimit(void *ptr, size_t size, size_t nmemb, void *stream);
enum bindtype {
K_BIND = 0,
K_BIND_EVENT,
K_BIND_ONOFF,
K_BIND_IPC,
K_BIND_FORCE,
K_BIND_SHUTDOWN,
K_BIND_ALIAS,
K_BIND_RPC,
K_BIND_INPUT
};
#define K_BROADCAST 1
#endif /* JS_H */