* Library to wrap GLib.spawn_async_with_pipes
*
* usage:
-*
-* Spawn = import.Spawn;
-*
-* simple version..
-* var output = Spawn.run({
-* cwd : '/home',
-* args : [ 'ls', '-l' ],
-* env : [], // optional
-* listeners : {
- output : function (line) { Seed.print(line); },
-* stderr : function (line) {Seed.print("ERROR" + line); },
-* input : function() { return 'xxx' },
-* }
-* });
-*
-*
+* v
*
-*
-*
-*var output = Spawn.run( SpawnConfig() {
+*var output = new Spawn( SpawnConfig() {
cwd = "/home", // empty string to default to homedirectory.
args = {"ls", "-l" },
evn = {},
delegate string SpawnInput();
-
-struct SpawnConfig
+
struct SpawnConfig {
public string cwd;
public string[] args;
async = false;
exceptions = false;
debug = false;
+ output = null;
+ stderr = null;
+ input = null;
}
}
if (!this.cfg.args.length) {
throw "No arguments";
}
+ this.run();
}
* @property err_ch {GLib.IOChannel} stderr io channel
*/
IOChannel err_ch = null;
-
+ /**
+ * @property err_src {int} the watch for errors
+ */
int err_src = -1;
-
+ /**
+ * @property err_src {int} the watch for output
+ */
int out_src = -1;
/**
* result is applied to object properties (eg. 'output' or 'stderr')
* @returns {Object} self.
*/
- public run : function()
+ public void run()
{
// using NONBLOCKING only works if io_add_watch
- //returns true/false in right conditions
- this.in_ch.set_flags (GLib.IOFlags.NONBLOCK);
- this.out_ch.set_flags (GLib.IOFlags.NONBLOCK);
- this.err_ch.set_flags (GLib.IOFlags.NONBLOCK);
-
+ //returns true/false in right conditions
+ this.in_ch.set_flags (GLib.IOFlags.NONBLOCK);
+ this.out_ch.set_flags (GLib.IOFlags.NONBLOCK);
+ this.err_ch.set_flags (GLib.IOFlags.NONBLOCK);
+
// add handlers for output and stderr.
- out_src= GLib.io_add_watch(this.out_ch, GLib.PRIORITY_DEFAULT,
- GLib.IOCondition.OUT + GLib.IOCondition.IN + GLib.IOCondition.PRI + GLib.IOCondition.HUP + GLib.IOCondition.ERR,
- function() {
-
- return _this.read(_this.out_ch);
-
- }
- );
- err_src= GLib.io_add_watch(this.err_ch, GLib.PRIORITY_DEFAULT,
- GLib.IOCondition.ERR + GLib.IOCondition.IN + GLib.IOCondition.PRI + GLib.IOCondition.OUT + GLib.IOCondition.HUP,
- function()
- {
- return _this.read(_this.err_ch);
-
- });
-
-
+
+ this.out_src = this.out_ch.add_watch (
+ IOCondition.OUT | IOCondition.IN | IOCondition.PRI | IOCondition.HUP | IOCondition.ERR ,
+ (channel, condition) => {
+ return this.read(_this.out_ch);
+ }
+ );
+ this.err_src = this.err_ch.add_watch (
+ IOCondition.OUT | IOCondition.IN | IOCondition.PRI | IOCondition.HUP | IOCondition.ERR ,
+ (channel, condition) => {
+ return this.read(_this.err_ch);
+ }
+ );
+
// call input..
- if (this.pid !== false) {
+ if (this.pid > -1) {
// child can exit before 1we get this far..
- if (this.listeners.input) {
- print("Trying to call listeners");
+ if (this.cfg.input != null) {
+ if (this.cfg.debug) print("Trying to call listeners");
try {
- this.write(this.listeners.input.call(this));
+ this.write(this.cfg.input());
// this probably needs to be a bit smarter...
//but... let's close input now..
this.in_ch.close();
- _this.in_ch = false;
-
-
-
-
+ this.in_ch = -1;
+
} catch (e) {
- tidyup();
+ this.tidyup();
throw e;
}
}
}
// async - if running - return..
- if (this.async && this.pid) {
- return this;
+ if (this.cfg.async && this.pid > -1) {
+ return;
}
// start mainloop if not async..
- if (this.pid !== false) {
- if (this.debug) {
+ if (this.pid > -1) {
+ if (this.cfg.debug) {
print("starting main loop");
}
-
- this.ctx = isSeed ? new GLib.MainLoop.c_new (null, false) : GLib.MainLoop.new (null, false);;
- this.ctx.run(false); // wait fore exit?
+ this.ctx = new MainLoop ();
+ loop.run(); // wait fore exit?
//print("main_loop done!");
} else {
- tidyup(); // tidyup get's called in main loop.
+ this.tidyup(); // tidyup get's called in main loop.
}
- if (this.exceptions && this.result != 0) {
- this.toString = function() { return this.stderr; };
- throw this; // we throw self...
+ if (this.cfg.exceptions && this.result != 0) {
+ //this.toString = function() { return this.stderr; };
+ ///throw new Exception this; // we throw self...
}
// finally throw, or return self..
- return this;
+ return;
- },
+ }
* @arg str {String} string to write to stdin of process
* @returns GLib.IOStatus (0 == error, 1= NORMAL)
*/
- write : function(str) // write a line to
+ integer write(str) // write a line to
{
- if (!this.in_ch) {
+ if (this.in_ch is null) {
return 0; // input is closed
}
//print("write: " + str);
//return ret.value;
return str.length;
- },
+ }
/**
* read from pipe and call appropriate listerner and add to output or stderr string.
}
};
-/**
- * @function run
- *
- * simple run a process - returns result, or throws stderr result...
- * @param cfg {Object} see spawn
- * @return {string} stdout output.
- */
-function run(cfg) {
- cfg.exceptions = true;
- cfg.async = false;
- var s = new Spawn(cfg);
- var ret = s.run();
- return s.output;
-}
- /*
+ /*
// test
try {
Seed.print(run({