add vty logp command to echo on all log targets

When reading SUT logs resulting from TTCN3 runs, it can be hard to figure out
which log section corresponds to which test code. Add a 'logp' command on VIEW
and ENABLE nodes that simply echos an arbitrary message on log output, useful
to set markers / explanations from the TTCN3 code, which then appear in all log
outputs and can make it trivial to figure out which log section is interesting.

	logging_vty_test# logp lglobal notice This is the log message
	DLGLOBAL NOTICE This is the log message

From TTCN3, could be used like this, e.g. in BSC_Tests.ttcn:

	private function f_logp(charstring log_msg) runs on MSC_ConnHdlr
	{
		// log on TTCN3 log output
	        log(log_msg);
		// log in stderr log
	        f_vty_transceive(BSCVTY, "logp lglobal notice " & log_msg);
	}

	...

	f_logp("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");

Change-Id: Ife5dc8999174c74e0d133729284fe526d6eaf8d9
diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c
index b785be4..243d6eb 100644
--- a/src/vty/logging_vty.c
+++ b/src/vty/logging_vty.c
@@ -991,6 +991,44 @@
 	install_element(CFG_LOG_NODE, cmd);
 }
 
+/* logp (<categories>) (debug|...|fatal) .LOGMESSAGE*/
+DEFUN(vty_logp,
+      vty_logp_cmd,
+      NULL, /* cmdstr is dynamically set in gen_vty_logp_cmd_strs(). */
+      NULL) /* same thing for helpstr. */
+{
+	int category = log_parse_category(argv[0]);
+	int level = log_parse_level(argv[1]);
+	char *str = argv_concat(argv, argc, 2);
+	LOGP(category, level, "%s\n", str);
+	return CMD_SUCCESS;
+}
+
+static void gen_vty_logp_cmd_strs(struct cmd_element *cmd)
+{
+	char *cmd_str = NULL;
+	char *doc_str = NULL;
+
+	assert_loginfo(__func__);
+
+	OSMO_ASSERT(cmd->string == NULL);
+	OSMO_ASSERT(cmd->doc == NULL);
+
+	osmo_talloc_asprintf(tall_log_ctx, cmd_str, "logp (");
+	osmo_talloc_asprintf(tall_log_ctx, doc_str,
+			     "Print a message on all log outputs; useful for placing markers in test logs\n");
+	add_category_strings(&cmd_str, &doc_str, osmo_log_info);
+	osmo_talloc_asprintf(tall_log_ctx, cmd_str, ") %s", LOG_LEVEL_ARGS);
+	osmo_talloc_asprintf(tall_log_ctx, doc_str, "%s", LOG_LEVEL_STRS);
+
+	osmo_talloc_asprintf(tall_log_ctx, cmd_str, " .LOGMESSAGE");
+	osmo_talloc_asprintf(tall_log_ctx, doc_str,
+			     "Arbitrary message to log on given category and log level\n");
+
+	cmd->string = cmd_str;
+	cmd->doc = doc_str;
+}
+
 /*! Register logging related commands to the VTY. Call this once from
  *  your application if you want to support those commands. */
 void logging_vty_add_cmds()
@@ -1026,6 +1064,9 @@
 	install_element_ve(&show_logging_vty_cmd);
 	install_element_ve(&show_alarms_cmd);
 
+	gen_vty_logp_cmd_strs(&vty_logp_cmd);
+	install_element_ve(&vty_logp_cmd);
+
 	install_node(&cfg_log_node, config_write_log);
 	install_element(CFG_LOG_NODE, &logging_fltr_all_cmd);
 	install_element(CFG_LOG_NODE, &logging_use_clr_cmd);