0day_dev/radare2-r2pipe/vala/r2pipe.vala
2020-08-07 13:48:00 -07:00

193 lines
4.8 KiB
Vala

public class R2Pipe {
public Pid child_pid;
public delegate void Callback (string s);
IOChannel input;
IOChannel output;
IOChannel error;
bool bootstrap = true;
bool in_async = true;
string reply = "";
private bool process_line (IOChannel channel, IOCondition condition, string stream_name) {
if (condition == IOCondition.HUP) {
//stderr.printf ("%s: The fd has been closed.\n", stream_name);
return false;
}
try {
string line;
size_t len;
size_t terpos;
channel.read_line (out line, out len, out terpos);
//stdout.printf ("%s: %s", stream_name, line);
reply += line;
if (line.length != len) {
if (bootstrap) {
reply = "";
bootstrap = false;
} else {
if (nextcb!= null) {
nextcb (reply);
// nextcb = null;
} else {
stdout.printf ("Command lost %s\n", reply);
}
reply = "";
}
}
} catch (IOChannelError e) {
stderr.printf ("%s: IOChannelError: %s\n", stream_name, e.message);
return false;
} catch (ConvertError e) {
stderr.printf ("%s: ConvertError: %s\n", stream_name, e.message);
return false;
}
return true;
}
private char[] str2arr(string str) {
char[] char_array = new char[str.length];
for (int i = 0; i < str.length; i++){
char_array[i] = (char)str.get_char(str.index_of_nth_char(i));
}
return char_array;
}
// XXX: use a list or so
weak Callback? nextcb = null;
public string? cmd(string cmd, Callback? cb = null) {
size_t w;
if (cb == null) {
return cmdSync(cmd);
}
nextcb = cb;
try {
input.write_chars (str2arr (cmd + "\n"), out w);
if (w != cmd.length + 1) {
stderr.printf ("Error writing to stdin %d\n", (int)w);
}
input.flush ();
} catch (IOChannelError e) {
stderr.printf ("IOChannelError: %s\n", e.message);
} catch (ConvertError e) {
stderr.printf ("ConvertError: %s\n", e.message);
}
return null;
}
public string? cmdSync(string cmd) {
size_t w;
try {
input.write_chars(str2arr (cmd + "\n"), out w);
if (w != cmd.length+1) {
stderr.printf ("Error writing to stdin %d\n", (int)w);
}
input.flush ();
string data = "";
while(true) {
char buf[1];
size_t ret;
var r = output.read_chars(buf, out ret);
if (r == IOStatus.ERROR || r== IOStatus.EOF) {
break;
}
if (buf[0] == 0)
break;
data += "%c".printf(buf[0]);
}
return data;
} catch (IOChannelError e) {
stderr.printf ("IOChannelError: %s\n", e.message);
} catch (ConvertError e) {
stderr.printf ("ConvertError: %s\n", e.message);
}
return null;
}
public R2Pipe(string file) {
R2Pipe.async(file);
}
public R2Pipe.async(string file) {
try {
string[] spawn_args = {"radare2", "-q0", file};
string[] spawn_env = Environ.get ();
int standard_input;
int standard_output;
int standard_error;
Process.spawn_async_with_pipes ("/",
spawn_args,
spawn_env,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
null,
out child_pid,
out standard_input,
out standard_output,
out standard_error);
// stdin:
input = new IOChannel.unix_new (standard_input);
// stdout:
output = new IOChannel.unix_new (standard_output);
output.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
return process_line (channel, condition, "stdout");
});
// stderr:
error = new IOChannel.unix_new (standard_error);
error.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
return process_line (channel, condition, "stderr");
});
} catch (SpawnError e) {
stdout.printf ("Error: %s\n", e.message);
}
}
public R2Pipe.sync(string file) {
in_async = false;
try {
string[] spawn_args = {"radare2", "-q0", file};
string[] spawn_env = Environ.get ();
int standard_input;
int standard_output;
int standard_error;
Process.spawn_async_with_pipes ("/",
spawn_args,
spawn_env,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
null,
out child_pid,
out standard_input,
out standard_output,
out standard_error);
// stdin:
input = new IOChannel.unix_new (standard_input);
// stdout:
output = new IOChannel.unix_new (standard_output);
output.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
return process_line (channel, condition, "stdout");
});
// stderr:
error = new IOChannel.unix_new (standard_error);
error.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
return process_line (channel, condition, "stderr");
});
char buf[1];
size_t ret;
output.read_chars(buf, out ret);
} catch (ConvertError e) {
stdout.printf ("ConvertError: %s\n", e.message);
} catch (IOChannelError e) {
stdout.printf ("IOChannelError: %s\n", e.message);
} catch (SpawnError e) {
stdout.printf ("SpawnError: %s\n", e.message);
}
}
}