1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*
* Copyright 2019 elementary, Inc. (https://elementary.io)
* Copyright 2011–2013 Lucas Baudin <xapantu@gmail.com>
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
/**
* This class is a wrapper to run an async command. It provides useful signals.
*/
[Version (deprecated = true, deprecated_since = "5.5.0", replacement = "GLib.AppInfo.create_from_commandline")]
public class Granite.Services.SimpleCommand : GLib.Object {
/**
* Emitted when the command is finished.
*/
public signal void done (int exit);
/**
* When the output changed (std.out and std.err).
*
* @param text the new text
*/
public signal void output_changed (string text);
/**
* When the standard output is changed.
*
* @param text the new text from std.out
*/
public signal void standard_changed (string text);
/**
* When the error output is changed.
*
* @param text the new text from std.err
*/
public signal void error_changed (string text);
/**
* The whole current standard output
*/
public string standard_output_str = "";
/**
* The whole current error output
*/
public string error_output_str = "";
/**
* The whole current output
*/
public string output_str = "";
GLib.IOChannel out_make;
GLib.IOChannel error_out;
string dir;
string command;
Pid pid;
/**
* Create a new object. You will have to call `run ()` when you want to run the command.
*
* @param dir The working dir
* @param command The command to execute (using absolute paths like /usr/bin/make causes less
* strange bugs).
*
*/
public SimpleCommand (string dir, string command) {
this.dir = dir;
this.command = command;
}
/**
* Launch the command. It is async.
*/
public void run () {
int standard_output = 0;
int standard_error = 0;
try {
Process.spawn_async_with_pipes (
dir,
command.split (" "),
null,
SpawnFlags.DO_NOT_REAP_CHILD,
null,
out pid,
null,
out standard_output,
out standard_error
);
} catch (Error e) {
critical ("Couldn't launch command %s in the directory %s: %s", command, dir, e.message);
}
ChildWatch.add (pid, (pid, exit) => {
done (exit);
});
out_make = new GLib.IOChannel.unix_new (standard_output);
out_make.add_watch (IOCondition.IN | IOCondition.HUP, (source, condition) => {
if (condition == IOCondition.HUP) {
return false;
}
string output = null;
try {
out_make.read_line (out output, null, null);
} catch (Error e) {
critical ("Error in the output retrieving of %s: %s", command, e.message);
}
standard_output_str += output;
output_str += output;
standard_changed (output);
output_changed (output);
return true;
});
error_out = new GLib.IOChannel.unix_new (standard_error);
error_out.add_watch (IOCondition.IN | IOCondition.HUP, (source, condition) => {
if (condition == IOCondition.HUP) {
return false;
}
string output = null;
try {
error_out.read_line (out output, null, null);
} catch (Error e) {
critical ("Error in the output retrieving of %s: %s", command, e.message);
}
error_output_str += output;
output_str += output;
error_changed (output);
output_changed (output);
return true;
});
}
}
|