A duktape cli-tool for Haiku

I’ve been working on a command-line-tool+, which has been a blessing for myself for the past few years.

It’s based upon Sami Vaarala’s Duktape, however, it’s written from scratch, but still using his library (with a minor addition).

Sami already released the “duk” tool, which is quite useful, however, I found that I had some needs it did not cover. I already have a Linux-version, which does most of what I need. I’ve made a Haiku-build, which has almost everything that the Linux-version has.

I’m able to make both a web-server and a web-client using this command-line tool. Here’s an example, just to give you a taste…

(On Haiku, the “!/opt/bin/duktape” shebang can be replaced by “!duktape”)

Simple HTTP-server:

#!/opt/bin/duktape

try{
var	server = new Net.httpServerSocket({})
    .listen(null, 11080)
    .on(“request”, function(request, response){
        if(/^get$/i.test(request.method)){
            response.end(“Hello from server\n”);
        }
    });
}catch(e){ File.err(e); }

Simple HTTP-client (a lot bigger):

#!/opt/bin/duktape

var site = "127.0.0.1:11080",
    address = Net.resolve(site);

try{
    var	socket = new Net.socket(),
        fragments = [];
    socket.eventMask = Events.POLLIN | Events.POLLOUT | Events.POLLHUP | Events.POLLERR;
    socket.on("activity", function(socket, events){
        if(Events.POLLIN & events){
            var	fragment = socket.reads(), response, i;
            if("string" === typeof(fragment) && fragment.length){
                if(!socket.responseHeader){
                    fragments.push(fragment);
                    response = fragments.join("");
                    i = response.indexOf("\15\12\15\12");
                    if(~i){
                        socket.responseHeader = response.substr(0, i);
                        fragment = response.substr(i + 4);
                    }
                    else{
                        fragment = "";
                    }
                }
                File.stdout(fragment);
            }
            else{
                socket.close();
            }
        }
        else if(Events.POLLOUT & events){
            socket.write(["GET / HTTP/1.0", "Host: " + site, ""].join("\15\12") + "\15\12");
            socket.shutdown(socket.SHUT_WR);
            socket.eventMask &= ~Events.POLLOUT;
        }
    });
    socket.connect(address);
}catch(e){ File.err(e); socket.close(); }

-Here the sockets are event-driven (using ppoll, as epoll is not available on Haiku). For a long time, it was sufficient for me to have blocking sockets only, but if one needs to write a server where two or more clients can connect, it’s a whole lot easier to use events. :wink:

… There’s also a convenience-method for iterating through a directory.

File.forEach(“/path/to/file/w?ldcard.*”, function(pathname, record, search){
    File.out("pathname:", pathname);
}, File.DTM_REG|File.DTM_DIR);

“File.out()” will output a newline, while “File.stdout()” will not. Same about “File.err()” and “File.stderr()”.

There is more and will be even more, but I can promise already, that it’s very convenient having this tool; I rarely use bash or perl now …

2 Likes