--- /dev/null
+/* $Id: js_signal.c,v 1.1 2005/07/19 19:27:28 mmondor Exp $ */
+
+/*
+ * Copyright (c) 2005, Matthew Mondor
+ * ALL RIGHTS RESERVED.
+ */
+
+/*
+ * Basic UNIX signal services for ECMAScript
+ *
+ * XXX
+ * I have to see what interface I want to export. There are several
+ * possibilities we could use:
+ * - Have the shell register signal handlers fore interesting events at
+ * startup and allow scripts to provide a handler function, which if
+ * exists upon reception of a signal, gets executed. We might then
+ * need to add extra custom checks in the shell for special signals
+ * which if the script doesn't end, might still end the process
+ * i.e. function would be expected to cause the script to exit upon
+ * reception of a SIGTERM signal...
+ * - Provide a sigaction-style interface so that the script would be
+ * able to define functions to execute upon reception of certain
+ * signals, or null or such for the signal to be ignored.
+ * This solution might allow better application customization.
+ * If assuming this interface, the following would be exported:
+ * - Signal class, through which static signal properties could be
+ * accessed for signal numbers I.E. Signal.SIGTERM.
+ * - A static method to create/set/unset/ignore a signal/handler
+ * Signal.sigaction()?
+ * It could be provided with the parameters:
+ * Signal.sigaction(FD.SIG*, obj);
+ * Where obj would contain fields sa_handler, sa_mask, sa_flags?
+ * Signal.kill(pid, sig);
+ * Signal.sigaltstack(...) ?
+ * Signal.sigprocmask(...)
+ * Signal.sigsuspend(mask)
+ * And maybe provide the sigsetops(3)? We possibly could just allow an
+ * array or such instead of sigset_t though if wanted.
+ * I'm not sure I want to provide sigsetjmp()/siglongjmp(). JavaScript has
+ * exceptions anyways. If allowing sigaltstack(), C would need to allocate
+ * the stacks, so a stack object would need to be exported or such. I
+ * don't think I want to support this as it's probably not needed by any of
+ * the applications I'll write, I don't want to write a threading library
+ * in JS.
+ */
+
+
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jsapi.h>
+
+
+
+/* Utility macros */
+#define QUEUE_EXCEPTION(s) do { \
+ JS_SetPendingException(cx, \
+ STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s)))); \
+} while (/* CONSTCOND */0)
+
+
+
+/* Prototypes */
+static JSBool signal_static_getProperty(JSContext *, JSObject *, jsval,
+ jsval *);
+
+static JSBool signal_sm_strerror(JSContext *, JSObject *, uintN, jsval *,
+ jsval *);
+
+
+
+/* Actual class parameters */
+static JSClass signal_class = {
+ "Signal", 0, JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
+ JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+};
+
+/* Provided static methods */
+static JSFunctionSpec signal_smethods[] = {
+ { "strerror", signal_sm_strerror, 1, 0, 0 },
+ { NULL, NULL, 0, 0, 0 }
+};
+
+/*
+ * Provided static properties.
+ * We use these to provide ECMAScript with the ability to use system-specific
+ * standard C constant macros without us having to tidiously map them
+ * individually, or to require other scripts to be used as headers to define
+ * them. Another possibility would have been to supply these parameters as
+ * string, but this would have required even slower remapping because of the
+ * parsing and string comparisions.
+ * We only include those which we consider necessary for now, others may be
+ * added easily as needed, provided that they are added in all three maps.
+ * I might perhaps develop macros and/or functions to map all these easily
+ * from a single map.
+ */
+enum signal_sprops {
+ SIGNAL_SP_SIGHUP,
+ SIGNAL_SP_SIGINT,
+ SIGNAL_SP_SIGQUIT,
+ SIGNAL_SP_SIGILL,
+ SIGNAL_SP_SIGTRAP,
+ SIGNAL_SP_SIGABRT,
+ SIGNAL_SP_SIGEMT,
+ SIGNAL_SP_SIGFPE,
+ SIGNAL_SP_SIGKILL,
+ SIGNAL_SP_SIGBUS,
+ SIGNAL_SP_SIGSEGV,
+ SIGNAL_SP_SIGSYS,
+ SIGNAL_SP_SIGPIPE,
+ SIGNAL_SP_SIGALRM,
+ SIGNAL_SP_SIGTERM,
+ SIGNAL_SP_SIGURG,
+ SIGNAL_SP_SIGSTOP,
+ SIGNAL_SP_SIGTSTP,
+ SIGNAL_SP_SIGCONT,
+ SIGNAL_SP_SIGCHLD,
+ SIGNAL_SP_SIGTTIN,
+ SIGNAL_SP_SIGTTOU,
+ SIGNAL_SP_SIGIO,
+ SIGNAL_SP_SIGXCPU,
+ SIGNAL_SP_SIGXFSZ,
+ SIGNAL_SP_SIGVTALRM,
+ SIGNAL_SP_SIGPROF,
+ SIGNAL_SP_SIGWINCH,
+ SIGNAL_SP_SIGINFO,
+ SIGNAL_SP_SIGUSR1,
+ SIGNAL_SP_SIGUSR2,
+ SIGNAL_SP_SIGPWR,
+
+ SIGNAL_SP_MAX
+};
+
+#define JSP_STATPROP \
+ (JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_READONLY | JSPROP_PERMANENT)
+#define JSP_STATPROPFS \
+ signal_static_getProperty, NULL
+
+static JSPropertySpec signal_sproperties[SIGNAL_SP_MAX + 1] = {
+ { "SIGHUP", SIGNAL_SP_SIGHUP, JSP_STATPROP, JSP_STATPROPFS },
+
+ { NULL, 0, 0, NULL, NULL }
+};
+
+#undef JSPROP_STATPROP
+#undef JSPROP_STATPROPFS
+
+/*
+ * The following array is necessary since we can only store unique tiny IDs,
+ * while some of our values may be duplicated. So let tinyid be unique (and
+ * limited to 8-bit), but map them to integers.
+ */
+
+static int signal_sprops_data[SIGNAL_SP_MAX] = {
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGEMT,
+ SIGFPE,
+ SIGKILL,
+ SIGBUS,
+ SIGSEGV,
+ SIGSYS,
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+ SIGURG,
+ SIGSTOP,
+ SIGTSTP,
+ SIGCONT,
+ SIGCHLD,
+ SIGTTIN,
+ SIGTTOU,
+ SIGIO,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGVTALRM,
+ SIGPROF,
+ SIGWINCH,
+ SIGINFO,
+ SIGUSR1,
+ SIGUSR2,
+ SIGPWR
+};
+
+
+
+/*
+ * Class control functions
+ */
+
+JSObject *
+js_InitSignalClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *class;
+
+ if ((class = JS_InitClass(cx, obj, NULL, &signal_class, NULL,
+ 0, NULL, NULL, signal_sproperties, signal_smethods)) == NULL) {
+ (void) fprintf(stderr, "Error initializing Signal class\n");
+ return NULL;
+ }
+
+ return class;
+}
+
+
+
+/*
+ * Static properties functions
+ */
+
+static JSBool
+signal_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint p;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ p = (int)JSVAL_TO_INT(id);
+ if (p < 0 || p >= SIGNAL_SP_MAX)
+ return JS_TRUE;
+
+ *vp = INT_TO_JSVAL(signal_sprops_data[
+ (int)signal_sproperties[p].tinyid]);
+
+ return JS_TRUE;
+}
+
+
+
+/*
+ * Static methods
+ */
+
+static JSBool
+signal_sm_strerror(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ int error;
+ JSString *string;
+
+ *rval = OBJECT_TO_JSVAL(NULL);
+
+ if (argc != 1) {
+ QUEUE_EXCEPTION("Wrong number of arguments");
+ return JS_FALSE;
+ }
+ if (!JSVAL_IS_INT(*argv)) {
+ QUEUE_EXCEPTION("Argument not an integer");
+ return JS_FALSE;
+ }
+ error = (int)JSVAL_TO_INT(*argv);
+
+ if ((string = JS_NewStringCopyZ(cx, "testXXX")) == NULL) {
+ QUEUE_EXCEPTION("Out of memory");
+ return JS_FALSE;
+ }
+
+ *rval = STRING_TO_JSVAL(string);
+
+ return JS_TRUE;
+}