console: best-effort std{out,err} redirection during console commands.
authorKrisztian Litkey <krisztian.litkey@intel.com>
Fri, 9 Nov 2012 17:25:10 +0000 (19:25 +0200)
committerKrisztian Litkey <krisztian.litkey@intel.com>
Fri, 9 Nov 2012 17:25:10 +0000 (19:25 +0200)
src/core/console-command.c
src/core/console.c
src/core/lua-bindings/lua-console.c
src/plugins/domain-control/plugin-domain-control.c
src/plugins/plugin-test.c
src/plugins/resource-native/plugin-resource-native.c

index 1d58ea2..7bfa496 100644 (file)
@@ -265,26 +265,28 @@ MRP_CONSOLE_GROUP(builtin_cmd_group, "", NULL, NULL, {
 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");
 }
 
 
@@ -335,7 +337,7 @@ static void debug_reset(mrp_console_t *c, void *user_data,
 
     mrp_debug_reset();
 
-    mrp_console_printf(c, "Debugging configuration has been reset to default.");
+    printf("Debugging configuration has been reset to default.");
 }
 
 
index 170ad83..21bd29f 100644 (file)
@@ -32,6 +32,7 @@
 #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 */
 
@@ -86,20 +91,24 @@ typedef struct {
     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);
 
@@ -162,6 +171,9 @@ mrp_console_t *mrp_create_console(mrp_context_t *ctx, mrp_console_req_t *req,
         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);
     }
@@ -193,6 +205,10 @@ static int purge_destroyed(mrp_console_t *mc)
         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);
 
@@ -358,6 +374,54 @@ int mrp_console_del_core_group(mrp_console_group_t *group)
 }
 
 
+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;
@@ -480,9 +544,29 @@ static ssize_t input_evt(mrp_console_t *mc, void *buf, size_t size)
 
  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:
index ec0babe..f224ebd 100644 (file)
@@ -15,12 +15,13 @@ static void eval_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
     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;
     }
 
@@ -39,7 +40,7 @@ static void eval_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
     }
 
     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);
 }
@@ -54,10 +55,11 @@ static void source_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
     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
@@ -66,7 +68,7 @@ static void source_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
     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;
     }
 
@@ -83,19 +85,17 @@ static void source_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
                 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));
     }
 }
 
index 934edc6..c0c240e 100644 (file)
@@ -28,11 +28,12 @@ static void plugin_exit(mrp_plugin_t *plugin)
 
 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__);
 }
 
 
index 8ced359..3e37f5b 100644 (file)
@@ -126,7 +126,6 @@ void one_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
 
     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]);
     }
 }
 
@@ -139,7 +138,6 @@ void two_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
 
     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]);
     }
 }
 
@@ -152,7 +150,6 @@ void three_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
 
     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]);
     }
 }
 
@@ -165,7 +162,6 @@ void four_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
 
     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]);
     }
 }
 
@@ -181,10 +177,9 @@ void db_script_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
     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);
     }
 }
@@ -208,21 +203,20 @@ void db_cmd_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
         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");
     }
 }
 
@@ -239,15 +233,15 @@ void resolve_cb(mrp_console_t *c, void *user_data, int argc, char **argv)
 
         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]);
     }
 }
 
@@ -507,7 +501,7 @@ static void success_cb(uint32_t tx, void *data)
 {
     mrp_console_t *c = data;
 
-    mrp_console_printf(c, "%s(): transaction %u\n", __FUNCTION__, tx);
+    printf("%s(): transaction %u\n", __FUNCTION__, tx);
 }
 
 
@@ -515,8 +509,8 @@ static void error_cb(uint32_t tx, mrp_tx_error_t err, void *data)
 {
     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");
 }
 
 
@@ -587,15 +581,15 @@ void signalling_cb_3(mrp_console_t *c, void *user_data, int argc, char **argv)
 
     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,
@@ -615,9 +609,9 @@ 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);
 }
 
 
@@ -635,7 +629,7 @@ void signalling_info_unregister_cb(mrp_console_t *c, void *user_data,
 
     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);
 }
 
 
@@ -643,11 +637,11 @@ static void dump_decision(mrp_console_t *c, ep_decision_t *msg)
 {
     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");
 }
 
@@ -660,7 +654,7 @@ static void recvfrom_evt(mrp_transport_t *t, void *data, uint16_t tag,
     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:
@@ -703,7 +697,7 @@ static void closed_evt(mrp_transport_t *t, int error, void *user_data)
     MRP_UNUSED(t);
     MRP_UNUSED(error);
 
-    mrp_console_printf(c, "Received closed event\n");
+    printf("Received closed event\n");
 }
 
 
@@ -736,13 +730,13 @@ void signalling_create_ep_cb(mrp_console_t *c, void *user_data,
     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;
     }
 
@@ -753,7 +747,7 @@ void signalling_create_ep_cb(mrp_console_t *c, void *user_data,
     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;
     }
 }
index f8b24b2..2ac4404 100644 (file)
@@ -128,16 +128,17 @@ static void print_zones_cb(mrp_console_t *c, void *user_data,
     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);
@@ -151,17 +152,17 @@ static void print_classes_cb(mrp_console_t *c, void *user_data,
     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);
     }
@@ -173,13 +174,14 @@ static void print_sets_cb(mrp_console_t *c, void *user_data,
 {
     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);
 }
 
 
@@ -188,13 +190,14 @@ static void print_owners_cb(mrp_console_t *c, void *user_data,
 {
     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)