osmo-bsc: Add VTY command show position
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index e98560d..56d62e5 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -521,6 +521,8 @@
 	BTS_LOC_FIX_3D = 2,
 };
 
+extern const struct value_string bts_loc_fix_names[];
+
 struct bts_location {
 	struct llist_head list;
 	time_t tstamp;
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index 83d1575..e89317d 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -95,6 +95,13 @@
 	{ 0, NULL }
 };
 
+const struct value_string bts_loc_fix_names[] = {
+	{ BTS_LOC_FIX_INVALID,	"invalid" },
+	{ BTS_LOC_FIX_2D,	"fix2d" },
+	{ BTS_LOC_FIX_3D,	"fix3d" },
+	{ 0, NULL }
+};
+
 struct cmd_node net_node = {
 	GSMNET_NODE,
 	"%s(config-net)# ",
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
index e4c6fea..be6dd52 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -212,13 +212,6 @@
 	talloc_free(cmd);
 }
 
-static const struct value_string valid_names[] = {
-	{ BTS_LOC_FIX_INVALID,	"invalid" },
-	{ BTS_LOC_FIX_2D,	"fix2d" },
-	{ BTS_LOC_FIX_3D,	"fix3d" },
-	{ 0, NULL }
-};
-
 static int location_equal(struct bts_location *a, struct bts_location *b)
 {
 	return ((a->tstamp == b->tstamp) && (a->valid == b->valid) && (a->lat == b->lat) &&
@@ -272,7 +265,7 @@
 	}
 
 	cmd->reply = talloc_asprintf(cmd, "%lu,%s,%f,%f,%f", curloc->tstamp,
-			get_value_string(valid_names, curloc->valid), curloc->lat, curloc->lon, curloc->height);
+			get_value_string(bts_loc_fix_names, curloc->valid), curloc->lat, curloc->lon, curloc->height);
 	if (!cmd->reply) {
 		cmd->reply = "OOM";
 		return CTRL_CMD_ERROR;
@@ -313,7 +306,7 @@
 	height = strtok_r(NULL, "\0", &saveptr);
 
 	curloc->tstamp = atol(tstamp);
-	curloc->valid = get_string_value(valid_names, valid);
+	curloc->valid = get_string_value(bts_loc_fix_names, valid);
 	curloc->lat = atof(lat);
 	curloc->lon = atof(lon);
 	curloc->height = atof(height);
@@ -361,7 +354,7 @@
 		goto err;
 
 	tstamp = atol(tstampstr);
-	valid = get_string_value(valid_names, validstr);
+	valid = get_string_value(bts_loc_fix_names, validstr);
 	lat = atof(latstr);
 	lon = atof(lonstr);
 	height = atof(heightstr);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 8cd80f9..fb38848 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -24,6 +24,8 @@
 
 #include <osmocom/core/talloc.h>
 
+#include <time.h>
+
 
 #define IPA_STR "IP.ACCESS specific\n"
 
@@ -512,6 +514,45 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(show_pos,
+      show_pos_cmd,
+      "show position",
+      SHOW_STR "Position information of the BTS\n")
+{
+	struct gsm_bts *bts;
+	struct bts_location *curloc;
+	struct tm time;
+	char timestr[50];
+
+	llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
+		if (llist_empty(&bts->loc_list)) {
+			vty_out(vty, "BTS Nr: %d position invalid%s", bts->nr,
+				VTY_NEWLINE);
+			continue;
+		}
+		curloc = llist_entry(bts->loc_list.next, struct bts_location, list);
+		if (gmtime_r(&curloc->tstamp, &time) == NULL) {
+			vty_out(vty, "Time conversion failed for BTS %d%s", bts->nr,
+				VTY_NEWLINE);
+			continue;
+		}
+		if (asctime_r(&time, timestr) == NULL) {
+			vty_out(vty, "Time conversion failed for BTS %d%s", bts->nr,
+				VTY_NEWLINE);
+			continue;
+		}
+		/* Last character in asctime is \n */
+		timestr[strlen(timestr)-1] = 0;
+
+		vty_out(vty, "BTS Nr: %d position: %s time: %s%s", bts->nr,
+			get_value_string(bts_loc_fix_names, curloc->valid), timestr,
+			VTY_NEWLINE);
+		vty_out(vty, " lat: %f lon: %f height: %f%s", curloc->lat, curloc->lon,
+			curloc->height, VTY_NEWLINE);
+	}
+	return CMD_SUCCESS;
+}
+
 int bsc_vty_init_extra(void)
 {
 	install_element(CONFIG_NODE, &cfg_net_msc_cmd);
@@ -551,6 +592,7 @@
 
 	install_element_ve(&show_statistics_cmd);
 	install_element_ve(&show_mscs_cmd);
+	install_element_ve(&show_pos_cmd);
 
 	return 0;
 }