static void debug_enable(mrp_console_t *c, void *user_data,
int argc, char **argv)
{
+ MRP_UNUSED(c);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
MRP_UNUSED(user_data);
mrp_debug_enable(TRUE);
- mrp_console_printf(c, "Debugging is now enabled.\n");
+ printf("Debugging is now enabled.\n");
}
static void debug_disable(mrp_console_t *c, void *user_data,
int argc, char **argv)
{
+ MRP_UNUSED(c);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
MRP_UNUSED(user_data);
mrp_debug_enable(FALSE);
- mrp_console_printf(c, "Debugging is now disabled.\n");
+ printf("Debugging is now disabled.\n");
}
mrp_debug_reset();
- mrp_console_printf(c, "Debugging configuration has been reset to default.");
+ printf("Debugging configuration has been reset to default.");
}
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
#include <murphy/common/mm.h>
#include <murphy/common/list.h>
#define CWARN COLOR""YELLOW
#define CERR COLOR""RED
+#define RFD 0
+#define WFD 1
+
+
#define MRP_CFG_MAXLINE 4096 /* input line length limit */
#define MRP_CFG_MAXARGS 64 /* command argument limit */
char prompt[MAX_PROMPT]; /* current prompt */
input_t in; /* input buffer */
mrp_list_hook_t hook; /* to list of active consoles */
+ int pout[2]; /* pipe for output proxying */
+ int ofd; /* saved fileno(stdout) */
+ int oblk; /* saved O_NONBLOCK for ofd */
+ int efd; /* saved fileno(stderr) */
+ int eblk; /* saved O_NONBLOCK for efd */
} console_t;
static int check_destroy(mrp_console_t *mc);
static int purge_destroyed(mrp_console_t *mc);
static FILE *console_fopen(mrp_console_t *mc);
+static void console_release_output(console_t *c);
static ssize_t input_evt(mrp_console_t *mc, void *buf, size_t size);
static void disconnected_evt(mrp_console_t *c, int error);
static ssize_t complete_evt(mrp_console_t *c, void *input, size_t isize,
char **completions, size_t csize);
-
-
static void register_commands(mrp_context_t *ctx);
static void unregister_commands(mrp_context_t *ctx);
c->in.line = 0;
c->in.fd = -1;
+ pipe(c->pout);
+ c->ofd = c->efd = -1;
+
mrp_list_append(&ctx->consoles, &c->hook);
mrp_set_console_prompt((mrp_console_t *)c);
}
fclose(c->stdout);
fclose(c->stderr);
+ console_release_output(c);
+ close(c->pout[0]);
+ close(c->pout[1]);
+
c->req.free(c->backend_data);
mrp_free(c);
}
+static void console_grab_output(console_t *c)
+{
+ int ofd = fileno(stdout);
+ int efd = fileno(stderr);
+ int blk;
+
+ if (c->ofd == -1 && c->pout[RFD] != -1) {
+ blk = fcntl(ofd, F_GETFL, 0);
+ c->oblk = (blk > 0 && (blk & O_NONBLOCK));
+ blk = fcntl(efd, F_GETFL, 0);
+ c->eblk = (blk > 0 && (blk & O_NONBLOCK));
+
+ c->ofd = dup(ofd);
+ dup2(c->pout[WFD], ofd);
+ fcntl(c->pout[RFD], F_SETFL, O_NONBLOCK);
+
+ c->efd = dup(efd);
+ dup2(c->pout[WFD], efd);
+ fcntl(c->pout[WFD], F_SETFL, O_NONBLOCK);
+ }
+}
+
+
+static void console_release_output(console_t *c)
+{
+ int ofd = fileno(stdout);
+ int efd = fileno(stderr);
+
+ if (c->ofd >= 0) {
+ dup2(c->ofd, ofd);
+ c->ofd = -1;
+ fcntl(ofd, F_SETFL, c->oblk);
+ }
+
+ if (c->efd >= 0) {
+ dup2(c->efd, efd);
+ c->efd = -1;
+ fcntl(efd, F_SETFL, c->eblk);
+ }
+}
+
+
+static int console_read_output(console_t *c, void *buf, size_t size)
+{
+ return read(c->pout[RFD], buf, size);
+}
+
+
static ssize_t input_evt(mrp_console_t *mc, void *buf, size_t size)
{
console_t *c = (console_t *)mc;
execute:
if (cmd != NULL) {
+ console_grab_output(c);
+
+ clearerr(stdout);
+ clearerr(stderr);
+
MRP_CONSOLE_BUSY(mc, {
cmd->tok(mc, grp->user_data, argc, argv);
});
+
+ {
+ char data[1024];
+ int size;
+
+ while ((size = console_read_output(c, data, sizeof(data))) > 0) {
+ dprintf(c->ofd, "%*.*s", size, size, data);
+ mrp_console_printf(mc, "%*.*s", size, size, data);
+ }
+
+ if (ferror(stdout) || ferror(stderr))
+ mrp_console_printf(mc, "[console output truncated...]\n");
+ }
+
+ console_release_output(c);
}
else {
unknown_command:
char code[1024], *p;
int i, n, l, len;
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
L = mrp_lua_get_lua_state();
if (L == NULL) {
- mrp_console_printf(c, "Lua runtime not available or initialized.");
+ printf("Lua runtime not available or initialized.");
return;
}
}
if (luaL_loadbuffer(L, code, len, "<console>") || lua_pcall(L, 0, 0, 0))
- mrp_console_printf(c, "Lua error: %s\n", lua_tostring(L, -1));
+ printf("Lua error: %s\n", lua_tostring(L, -1));
lua_settop(L, 0);
}
ssize_t len;
int fd;
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
if (argc != 3) {
- mrp_console_printf(c, "Invalid arguments, expecting a single path.");
+ printf("Invalid arguments, expecting a single path.");
return;
}
else
L = mrp_lua_get_lua_state();
if (L == NULL) {
- mrp_console_printf(c, "Lua runtime not available or initialized.");
+ printf("Lua runtime not available or initialized.");
return;
}
if (len > 0) {
if (luaL_loadbuffer(L, code, len, path) != 0 ||
lua_pcall(L, 0, 0, 0) != 0)
- mrp_console_printf(c, "Lua error: %s\n",
- lua_tostring(L, -1));
+ printf("Lua error: %s\n", lua_tostring(L, -1));
lua_settop(L, 0);
}
}
else
- mrp_console_printf(c, "Failed to open %s (%d: %s).", path,
- errno, strerror(errno));
+ printf("Failed to open %s (%d: %s).", path,
+ errno, strerror(errno));
}
else
- mrp_console_printf(c, "Failed to open %s (%d: %s).", path,
- errno, strerror(errno));
+ printf("Failed to open %s (%d: %s).", path, errno, strerror(errno));
}
}
static void cmd_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
{
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
- mrp_console_printf(c, "domctrl:%s() called...\n", __FUNCTION__);
+ printf("domctrl:%s() called...\n", __FUNCTION__);
}
for (i = 0; i < argc; i++) {
printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
- mrp_console_printf(c, "%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
}
}
for (i = 0; i < argc; i++) {
printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
- mrp_console_printf(c, "%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
}
}
for (i = 0; i < argc; i++) {
printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
- mrp_console_printf(c, "%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
}
}
for (i = 0; i < argc; i++) {
printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
- mrp_console_printf(c, "%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]);
}
}
for (i = 2; i < argc; i++) {
tx = mqi_begin_transaction();
if (mql_exec_file(argv[i]) < 0)
- mrp_console_printf(c, "failed to execute DB script: %s\n",
- strerror(errno));
+ printf("failed to execute DB script: %s\n", strerror(errno));
else
- mrp_console_printf(c, "DB script executed OK\n");
+ printf("DB script executed OK\n");
mqi_commit_transaction(tx);
}
}
n -= l;
if ((tx = mqi_begin_transaction()) == MQI_HANDLE_INVALID)
- mrp_console_printf(c, "failed to create DB transaction\n");
+ printf("failed to create DB transaction\n");
r = mql_exec_string(mql_result_string, buf);
if (!mql_result_is_success(r)) {
- mrp_console_printf(c, "failed to execute DB command '%s'\n",
- buf);
+ printf("failed to execute DB command '%s'\n", buf);
}
else {
- mrp_console_printf(c, "DB command executed OK\n");
- mrp_console_printf(c, "%s\n", mql_result_string_get(r));
+ printf("DB command executed OK\n");
+ printf("%s\n", mql_result_string_get(r));
}
mql_result_free(r);
if (mqi_commit_transaction(tx) < 0)
- mrp_console_printf(c, "failed to commit DB transaction\n");
+ printf("failed to commit DB transaction\n");
}
}
if (ctx->r != NULL) {
if (mrp_resolver_update_target(ctx->r, target, NULL) > 0)
- mrp_console_printf(c, "'%s' updated OK.\n", target);
+ printf("'%s' updated OK.\n", target);
else
- mrp_console_printf(c, "Failed to update '%s'.\n", target);
+ printf("Failed to update '%s'.\n", target);
}
else
- mrp_console_printf(c, "Resolver/ruleset is not available.\n");
+ printf("Resolver/ruleset is not available.\n");
}
else {
- mrp_console_printf(c, "Usage: %s %s <target-name>\n", argv[0], argv[1]);
+ printf("Usage: %s %s <target-name>\n", argv[0], argv[1]);
}
}
{
mrp_console_t *c = data;
- mrp_console_printf(c, "%s(): transaction %u\n", __FUNCTION__, tx);
+ printf("%s(): transaction %u\n", __FUNCTION__, tx);
}
{
mrp_console_t *c = data;
- mrp_console_printf(c, "%s(): transaction %u error: %s\n", __FUNCTION__,
- tx, (err == MRP_TX_ERROR_NACKED) ? "NACK" : "no reply");
+ printf("%s(): transaction %u error: %s\n", __FUNCTION__,
+ tx, (err == MRP_TX_ERROR_NACKED) ? "NACK" : "no reply");
}
ret = mrp_tx_close_signal(tx);
- mrp_console_printf(c, "%s(): tried to send a cancelled transction %u -- success %i\n",
- __FUNCTION__, tx, ret);
+ printf("%s(): tried to send a cancelled transction %u -- success %i\n",
+ __FUNCTION__, tx, ret);
}
static void info_cb(char *msg, void *data)
{
mrp_console_t *c = data;
- mrp_console_printf(c, "received msg '%s'\n", msg);
+ printf("received msg '%s'\n", msg);
}
void signalling_info_register_cb(mrp_console_t *c, void *user_data,
ret = mrp_info_register(ep, info_cb, c);
if (ret < 0)
- mrp_console_printf(c, "Failed to register back channel to EP '%s'\n", ep);
+ printf("Failed to register back channel to EP '%s'\n", ep);
else
- mrp_console_printf(c, "Registered back channel to EP '%s'\n", ep);
+ printf("Registered back channel to EP '%s'\n", ep);
}
mrp_info_unregister(ep);
- mrp_console_printf(c, "Unregistered back channel to EP '%s'\n", ep);
+ printf("Unregistered back channel to EP '%s'\n", ep);
}
{
uint i;
- mrp_console_printf(c, "Message contents:\n");
+ printf("Message contents:\n");
for (i = 0; i < msg->n_rows; i++) {
- mrp_console_printf(c, "row %d: '%s'\n", i+1, msg->rows[i]);
+ printf("row %d: '%s'\n", i+1, msg->rows[i]);
}
- mrp_console_printf(c, "%s required.\n\n",
+ printf("%s required.\n\n",
msg->reply_required ? "Reply" : "No reply");
}
MRP_UNUSED(addr);
MRP_UNUSED(addrlen);
- mrp_console_printf(c, "Received message (0x%02x)\n", tag);
+ printf("Received message (0x%02x)\n", tag);
switch (tag) {
case TAG_POLICY_DECISION:
MRP_UNUSED(t);
MRP_UNUSED(error);
- mrp_console_printf(c, "Received closed event\n");
+ printf("Received closed event\n");
}
alen = mrp_transport_resolve(NULL, "internal:signalling", &addr, sizeof(addr), NULL);
if (alen <= 0) {
- mrp_console_printf(c, "Error: resolving address failed!\n");
+ printf("Error: resolving address failed!\n");
return;
}
ret = mrp_transport_connect(t, &addr, alen);
if (ret == 0) {
- mrp_console_printf(c, "Error: connect failed!\n");
+ printf("Error: connect failed!\n");
return;
}
ret = mrp_transport_senddata(t, &msg, TAG_REGISTER);
if (!ret) {
- mrp_console_printf(c, "Failed to send register message\n");
+ printf("Failed to send register message\n");
return;
}
}
const char **zone_names;
int i;
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
- mrp_console_printf(c, "Zones:\n");
+ printf("Zones:\n");
if ((zone_names = mrp_zone_get_all_names(0, NULL))) {
for (i = 0; zone_names[i]; i++)
- mrp_console_printf (c, " %s\n", zone_names[i]);
+ printf(" %s\n", zone_names[i]);
mrp_free(zone_names);
const char **class_names;
int i;
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
- mrp_console_printf(c, "Application classes:\n");
+ printf("Application classes:\n");
if ((class_names = mrp_application_class_get_all_names(0, NULL))) {
for (i = 0; class_names[i]; i++)
- mrp_console_printf(c, " %s\n", class_names[i]);
-
+ printf(" %s\n", class_names[i]);
mrp_free(class_names);
}
{
char buf[8192];
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
mrp_application_class_print(buf, sizeof(buf));
- mrp_console_printf(c, "%s", buf);
+ printf("%s", buf);
}
{
char buf[2048];
+ MRP_UNUSED(c);
MRP_UNUSED(user_data);
MRP_UNUSED(argc);
MRP_UNUSED(argv);
mrp_resource_owner_print(buf, sizeof(buf));
- mrp_console_printf(c, "%s", buf);
+ printf("%s", buf);
}
static int set_default_configuration(void)