Added Dir object wrapping around opendir(3).
authorMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 8 Sep 2006 12:50:47 +0000 (12:50 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 8 Sep 2006 12:50:47 +0000 (12:50 +0000)
mmsoftware/js/classes/js_dir.c [new file with mode: 0644]
mmsoftware/js/classes/js_dir.h [new file with mode: 0644]
mmsoftware/js/js-appserv/src/GNUmakefile
mmsoftware/js/js-appserv/src/js-appserv.c
mmsoftware/js/js-sh/app/httpd/httpd.js
mmsoftware/js/js-sh/src/GNUmakefile
mmsoftware/js/js-sh/src/js-sh.c

diff --git a/mmsoftware/js/classes/js_dir.c b/mmsoftware/js/classes/js_dir.c
new file mode 100644 (file)
index 0000000..5407127
--- /dev/null
@@ -0,0 +1,339 @@
+/* $Id: js_dir.c,v 1.1 2006/09/08 12:50:43 mmondor Exp $ */
+
+/*
+ * Copyright (c) 2006, Matthew Mondor
+ * ALL RIGHTS RESERVED.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/dirent.h>
+
+#include <stdint.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jsapi.h>
+
+#include <js_dir.h>
+
+
+
+
+#define QUEUE_EXCEPTION(s)     do {                                    \
+       JS_SetPendingException(cx,                                      \
+           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
+} while (/* CONSTCOND */0)
+
+
+struct property_spec {
+       const char      *name;
+       int             value;
+};
+
+#define SP(n) \
+    { #n, n }
+
+
+
+/*
+ * Static prototypes
+ */
+static JSBool  dir_constructor(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static void    dir_finalize(JSContext *, JSObject *);
+
+static JSBool  dir_m_read(JSContext *, JSObject *, uintN, jsval *, jsval *);
+static JSBool  dir_m_tell(JSContext *, JSObject *, uintN, jsval *, jsval *);
+static JSBool  dir_m_seek(JSContext *, JSObject *, uintN, jsval *, jsval *);
+static JSBool  dir_m_rewind(JSContext *, JSObject *, uintN, jsval *,
+                   jsval *);
+static JSBool  dir_m_close(JSContext *, JSObject *, uintN, jsval *, jsval *);
+
+
+
+/*
+ * Static globals
+ */
+
+/* PG class */
+static JSClass dir_class = {
+       "Dir", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
+       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
+       JS_ConvertStub, dir_finalize
+};
+
+/* Provided methods */
+static JSFunctionSpec dir_methods[] = {
+       { "read", dir_m_read, 0, 0, 0 },
+       { "tell", dir_m_tell, 0, 0, 0 },
+       { "seek", dir_m_seek, 1, 0, 0 },
+       { "rewind", dir_m_rewind, 0, 0, 0 },
+       { "close", dir_m_close, 0, 0, 0 }
+};
+
+/* Static properties */
+
+static struct property_spec    dir_sprops[] = {
+       SP(DT_UNKNOWN),
+       SP(DT_FIFO),
+       SP(DT_CHR),
+       SP(DT_DIR),
+       SP(DT_BLK),
+       SP(DT_REG),
+       SP(DT_LNK),
+       SP(DT_SOCK),
+#ifdef DT_WHT
+       SP(DT_WHT)
+#endif
+};
+
+
+
+/*
+ * Dir object control
+ */
+
+JSObject *
+js_InitDirClass(JSContext *cx, JSObject *obj)
+{
+       JSObject                *proto, *ctor;
+       struct property_spec    *sp;
+
+       if ((proto = JS_InitClass(cx, obj, NULL, &dir_class, dir_constructor,
+           0, NULL, dir_methods, NULL, NULL)) == NULL) {
+               (void) fprintf(stderr, "Error initializing CGI class\n");
+               goto err;
+       }
+
+       /* Create static properties. */
+       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
+               (void) fprintf(stderr, "Dir: JS_GetConstructor == NULL\n");
+               return NULL;
+       }
+       for (sp = dir_sprops; sp->name != NULL; sp++) {
+               if (JS_DefineProperty(cx, ctor, sp->name,
+                   INT_TO_JSVAL(sp->value), NULL, NULL,
+                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
+                       (void) fprintf(stderr,
+                           "Dir: Error defining property %s\n", sp->name);
+                       return NULL;
+               }
+       }
+
+       return proto;
+
+err:
+       return NULL;
+}
+
+static JSBool
+dir_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+    jsval *rval)
+{
+       DIR     *dir = NULL;
+       char    *path;
+
+       if (!JS_IsConstructing(cx)) {
+               QUEUE_EXCEPTION("Constructor called as a function");
+               goto err;
+       }
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               goto err;
+       }
+       if (!JSVAL_IS_STRING(argv[0])) {
+               QUEUE_EXCEPTION("Argument not a string");
+               goto err;
+       }
+
+       path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
+       if ((dir = opendir(path)) == NULL) {
+               char    str[256];
+
+               (void) snprintf(str, sizeof(str), "opendir('%s'): %s",
+                   str, strerror(errno));
+               QUEUE_EXCEPTION(str);
+               goto err;
+       }
+
+       if (!JS_SetPrivate(cx, obj, dir)) {
+               QUEUE_EXCEPTION("Internal error!");
+               goto err;
+       }
+
+       return JS_TRUE;
+
+err:
+       *rval = OBJECT_TO_JSVAL(NULL);
+       if (dir != NULL)
+               (void) closedir(dir);
+
+       return JS_FALSE;
+}
+
+static void
+dir_finalize(JSContext *cx, JSObject *obj)
+{
+       DIR     *dir;
+
+       if ((dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL)) != NULL) {
+               (void) closedir(dir);
+               (void) JS_SetPrivate(cx, obj, NULL);
+       }
+}
+
+
+
+/* Methods */
+static JSBool
+dir_m_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       DIR             *dir;
+       struct dirent   *de;
+       JSObject        *o;
+       jsval           val;
+       JSString        *str;
+
+       if (argc != 0) {
+               QUEUE_EXCEPTION("Function allows no arguments");
+               *rval = OBJECT_TO_JSVAL(NULL);
+               return JS_FALSE;
+       }
+
+       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
+       assert(dir != NULL);
+
+       if ((de = readdir(dir)) == NULL) {
+               *rval = OBJECT_TO_JSVAL(NULL);
+               return JS_TRUE;
+       }
+
+       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
+               QUEUE_EXCEPTION("Internal error!");
+               *rval = OBJECT_TO_JSVAL(NULL);
+               return JS_FALSE;
+       }
+       *rval = OBJECT_TO_JSVAL(o);
+
+       /* d_fileno is u_int32_t and so could exceed a JS int, so use this */
+       if (!JS_NewNumberValue(cx, (jsdouble)de->d_fileno, &val) ||
+           !JS_DefineProperty(cx, o, "fileno", val, NULL, NULL,
+           JSPROP_ENUMERATE))
+               goto err;
+
+       if (!JS_DefineProperty(cx, o, "type", INT_TO_JSVAL(de->d_type), NULL,
+           NULL, JSPROP_ENUMERATE))
+               goto err;
+
+       if ((str = JS_NewStringCopyN(cx, de->d_name, de->d_namlen)) == NULL ||
+           !JS_DefineProperty(cx, o, "name", STRING_TO_JSVAL(str), NULL,
+           NULL, JSPROP_ENUMERATE))
+               goto err;
+
+       return JS_TRUE;
+
+err:
+       QUEUE_EXCEPTION("Internal error!");
+       *rval = OBJECT_TO_JSVAL(NULL);
+       return JS_FALSE;
+}
+
+static JSBool
+dir_m_tell(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       DIR     *dir;
+       long    v;
+
+       if (argc != 0) {
+               QUEUE_EXCEPTION("Function allows no arguments");
+               *rval = OBJECT_TO_JSVAL(NULL);
+               return JS_FALSE;
+       }
+
+       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
+       assert(dir != NULL);
+
+       v = telldir(dir);
+
+       if (!JS_NewNumberValue(cx, (jsdouble)v, rval)) {
+               QUEUE_EXCEPTION("Internal error!");
+               *rval = OBJECT_TO_JSVAL(NULL);
+               return JS_FALSE;
+       }
+
+       return JS_TRUE;
+}
+
+static JSBool
+dir_m_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       DIR             *dir;
+       jsdouble        v;
+
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       if (argc != 1) {
+               QUEUE_EXCEPTION("Wrong number of arguments");
+               return JS_FALSE;
+       }
+       if (!JSVAL_IS_NUMBER(argv[0]) ||
+           !JS_ValueToNumber(cx, argv[0], &v)) {
+               QUEUE_EXCEPTION("Argument 1 not a number");
+               return JS_FALSE;
+       }
+
+       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
+       assert(dir != NULL);
+
+       seekdir(dir, (long)v);
+
+       return JS_TRUE;
+}
+
+static JSBool
+dir_m_rewind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       DIR     *dir;
+
+       *rval = OBJECT_TO_JSVAL(NULL);
+
+       if (argc != 0) {
+               QUEUE_EXCEPTION("Function allows no arguments");
+               return JS_FALSE;
+       }
+
+       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
+       assert(dir != NULL);
+
+       rewinddir(dir);
+
+       return JS_TRUE;
+}
+
+static JSBool
+dir_m_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       DIR     *dir;
+
+       if (argc != 0) {
+               QUEUE_EXCEPTION("Function allows no arguments");
+               *rval = OBJECT_TO_JSVAL(NULL);
+               return JS_FALSE;
+       }
+
+       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
+       assert(dir != NULL);
+
+       *rval = INT_TO_JSVAL(closedir(dir));
+       (void) JS_SetPrivate(cx, obj, NULL);
+
+       return JS_TRUE;
+}
diff --git a/mmsoftware/js/classes/js_dir.h b/mmsoftware/js/classes/js_dir.h
new file mode 100644 (file)
index 0000000..9bd504b
--- /dev/null
@@ -0,0 +1,15 @@
+/* $Id: js_dir.h,v 1.1 2006/09/08 12:50:43 mmondor Exp $ */
+
+/*
+ * Copyright (c) 2006, Matthew Mondor
+ * ALL RIGHTS RESERVED.
+ */
+
+#ifndef JSDIR_H
+#define JSDIR_H
+
+#include <js_dir.h>
+
+extern JSObject        *js_InitDirClass(JSContext *, JSObject *);
+
+#endif
index 3aa9f8d..4c91606 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: GNUmakefile,v 1.1 2006/08/20 06:59:00 mmondor Exp $
+# $Id: GNUmakefile,v 1.2 2006/09/08 12:50:45 mmondor Exp $
 
 CFLAGS += -Wall -DDEBUG
 
@@ -13,7 +13,7 @@ PG_LDFLAGS += -lpq
 
 MMOBJS := $(addprefix ../../../mmlib/,mmpool.o mmlog.o mmreadcfg.o \
        mmstring.o mmhash.o mmalarm.o mmheap.o mmlimitrate.o mmserver2.o)
-JSOBJS := $(addprefix ../../classes/,js_errno.o js_fd.o js_pgsql.o)
+JSOBJS := $(addprefix ../../classes/,js_errno.o js_fd.o js_pgsql.o js_dir.o)
 
 
 CFLAGS += $(JS_CFLAGS) $(PG_CFLAGS) -I. -I../../../mmlib -I../../classes
index 9a979c2..7bdccfc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: js-appserv.c,v 1.1 2006/08/20 06:59:00 mmondor Exp $ */
+/* $Id: js-appserv.c,v 1.2 2006/09/08 12:50:45 mmondor Exp $ */
 
 /*
  * Copyright (C) 2006, Matthew Mondor
@@ -75,6 +75,7 @@
 #include <js_errno.h>
 #include <js_fd.h>
 #include <js_pgsql.h>
+#include <js_dir.h>
 
 
 
@@ -676,6 +677,9 @@ context_create(JSRuntime *rt, size_t stacksize, JSObject **obj)
        if (!js_InitPGClass(ctx, *obj)) {
                syslog(LOG_NOTICE, "context_create() - js_InitPGClass()");
        }
+       if (!js_InitDirClass(ctx, *obj)) {
+               syslog(LOG_NOTICE, "context_create() - js_InitDirClass()");
+       }
 
        /* Set our GC handler callback */
        (void) JS_SetBranchCallback(ctx, branch_callback);
index 604e87c..ffddd40 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: httpd.js,v 1.39 2006/08/22 13:51:58 mmondor Exp $ */
+/* $Id: httpd.js,v 1.40 2006/09/08 12:50:46 mmondor Exp $ */
 
 /*
  * Copyright (c) 2005-2006, Matthew Mondor
@@ -76,7 +76,7 @@
  * Server identification
  */
 const SERVER_VERSION = 'mmondor_js_httpd/0.1.0 (NetBSD)';
-const SERVER_CVSID = '$Id: httpd.js,v 1.39 2006/08/22 13:51:58 mmondor Exp $';
+const SERVER_CVSID = '$Id: httpd.js,v 1.40 2006/09/08 12:50:46 mmondor Exp $';
 
 
 
@@ -686,15 +686,19 @@ function state_http_transfer_file(time)
                        /*
                         * XXX For some reason, we now get problems with
                         * immediate writing mode.  Dandling client and file
-                        * descriptors remain, like if HUP was ignored for
-                        * some reason.
+                        * descriptors remain, like if HUP was ignored.
+                        * Very odd.
                         */
                        if (this.bwrite(this.transfer_data, false, false)
                            != -1) {
                                this.transfer_state = TSTATE_READ;
                                this.updateTimeout(time);
-                       } else if (this.berror != this.BEAGAIN)
-                               stat = PSTAT_CLOSE_ERROR;
+                       } else {
+                               if (this.berror == this.BEAGAIN)
+                                       this.events |= FD.POLLOUT;
+                               else
+                                       stat = PSTAT_CLOSE_ERROR;
+                       }
                }
        }
 
index fb699dc..ccf4735 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: GNUmakefile,v 1.1 2006/07/22 04:43:20 mmondor Exp $
+# $Id: GNUmakefile,v 1.2 2006/09/08 12:50:47 mmondor Exp $
 
 #CFLAGS += -g
 CFLAGS += -Wall
@@ -10,7 +10,8 @@ PG_CFLAGS := $(shell pg_config --cppflags)
 PG_LDFLAGS := $(shell pg_config --ldflags)
 PG_LDFLAGS += -lpq
 
-OBJS := $(addprefix ../../classes/,js_fd.o js_errno.o js_signal.o js_pgsql.o)
+OBJS := $(addprefix ../../classes/,js_fd.o js_errno.o js_signal.o js_pgsql.o \
+       js_dir.o)
 OBJS += js-sh.o
 
 CFLAGS += $(JS_CFLAGS) $(PG_CFLAGS) -I../../classes -Wall
index 5e7afdf..d23cbc2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: js-sh.c,v 1.4 2006/08/12 13:48:57 mmondor Exp $ */
+/* $Id: js-sh.c,v 1.5 2006/09/08 12:50:47 mmondor Exp $ */
 
 /*
  * Copyright (c) 2004-2005, Matthew Mondor
@@ -40,6 +40,7 @@
 #include <js_errno.h>
 #include <js_signal.h>
 #include <js_pgsql.h>
+#include <js_dir.h>
 
 
 
@@ -63,7 +64,7 @@ typedef struct {
        JSRuntime       *rt;
        JSContext       *ctx;
        JSObject        *global, *class_fd, *class_errno, *class_signal,
-                       *class_pgsql;
+                       *class_pgsql, *class_dir;
 } js_context_t;
 
 /*
@@ -237,6 +238,8 @@ js_context_init(size_t gc_size, size_t stack_size)
            (cctx->class_signal = js_InitSignalClass(cctx->ctx, cctx->global))
                == NULL ||
            (cctx->class_pgsql = js_InitPGClass(cctx->ctx, cctx->global))
+               == NULL  ||
+           (cctx->class_dir = js_InitDirClass(cctx->ctx, cctx->global))
                == NULL) {
                /* An error, free any partially allocated resources */
                if (cctx != NULL)