From a72236a1d0effb1fe985f5685d40e6dc33ab65a3 Mon Sep 17 00:00:00 2001
From: Harald Welte <laforge@gnumonks.org>
Date: Fri, 27 Sep 2013 22:42:41 +0200
Subject: permit gsmd and libgsm to handle multiple instances

By using differntly-named unix domain sockets, we can run
multiple gsmd instances in parallel.
---
 include/gsmd/gsmd.h       |  1 +
 include/libgsmd/libgsmd.h |  1 +
 src/gsmd/gsmd.c           |  7 ++++++-
 src/gsmd/usock.c          |  9 ++++++++-
 src/libgsmd/libgsmd.c     | 19 ++++++++++++++++---
 src/util/libgsmd-tool.c   | 11 ++++++++---
 6 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/include/gsmd/gsmd.h b/include/gsmd/gsmd.h
index 585d78d..47bc43d 100644
--- a/include/gsmd/gsmd.h
+++ b/include/gsmd/gsmd.h
@@ -74,6 +74,7 @@ struct gsmd;
 #define GSMD_ATCMD_TIMEOUT	60	/* If doesn get respond within 60 secs, discard */
 
 struct gsmd {
+	unsigned int instance;
 	unsigned int flags;
 	int interpreter_ready;
 	struct gsmd_fd gfd_uart;
diff --git a/include/libgsmd/libgsmd.h b/include/libgsmd/libgsmd.h
index a6a4252..3fce0f0 100644
--- a/include/libgsmd/libgsmd.h
+++ b/include/libgsmd/libgsmd.h
@@ -49,6 +49,7 @@ typedef int lgsm_msg_handler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh);
 
 /* initialize usage of libgsmd, obtain handle for othe API calls */
 extern struct lgsm_handle *lgsm_init(const char *device);
+extern struct lgsm_handle *lgsm_init_inst(unsigned int instance);
 
 /* Terminate usage of libgsmd */
 extern int lgsm_exit(struct lgsm_handle *lh); 
diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c
index 9389f5f..20daa7f 100644
--- a/src/gsmd/gsmd.c
+++ b/src/gsmd/gsmd.c
@@ -317,6 +317,7 @@ static struct option opts[] = {
 	{ "version", 0, NULL, 'V' },
 	{ "daemon", 0, NULL, 'd' },
 	{ "help", 0, NULL, 'h' },
+	{ "instance", 1, NULL, 'i' },
 	{ "device", 1, NULL, 'p' },
 	{ "speed", 1, NULL, 's' },
 	{ "logfile", 1, NULL, 'l' },
@@ -347,6 +348,7 @@ static void print_usage(void)
 	       "\t-V\t--version\tDisplay program version\n"
 	       "\t-d\t--daemon\tDeamonize\n"
 	       "\t-h\t--help\t\tDisplay this help message\n"
+	       "\t-i\t--instance <0-255>\t\tInstance number to use\n"
 	       "\t-p dev\t--device dev\tSpecify serial device to be used\n"
 	       "\t-s spd\t--speed spd\tSpecify speed in bps (9600,38400,115200,...)\n"
 	       "\t-F\t--hwflow\tHardware Flow Control (RTS/CTS)\n"
@@ -396,7 +398,7 @@ int main(int argc, char **argv)
 	print_header();
 
 	/*FIXME: parse commandline, set daemonize, device, ... */
-	while ((argch = getopt_long(argc, argv, "FVLdhp:s:l:e:v:m:w:", opts, NULL)) != -1) {
+	while ((argch = getopt_long(argc, argv, "FVLdhi:p:s:l:e:v:m:w:", opts, NULL)) != -1) {
 		switch (argch) {
 		case 'V':
 			print_version();
@@ -416,6 +418,9 @@ int main(int argc, char **argv)
 			print_usage();
 			exit(0);
 			break;
+		case 'i':
+			g.instance = atoi(optarg);
+			break;
 		case 'p':
 			device = optarg;
 			break;
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index f258fd6..41814c8 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -1734,7 +1734,14 @@ int usock_init(struct gsmd *g)
 	
 	memset(&sun, 0, sizeof(sun));
 	sun.sun_family = AF_UNIX;
-	memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
+	if (g->instance == 0) {
+		memcpy(sun.sun_path, GSMD_UNIX_SOCKET,
+		       sizeof(GSMD_UNIX_SOCKET));
+	} else {
+		sun.sun_path[0] = '\0';
+		snprintf(sun.sun_path+1, sizeof(sun.sun_path)-1, "gsmd.%u",
+			 g->instance);
+	}
 
 	rc = bind(fd, (struct sockaddr *)&sun, sizeof(sun));
 	if (rc < 0) {
diff --git a/src/libgsmd/libgsmd.c b/src/libgsmd/libgsmd.c
index 1626b04..03642ea 100644
--- a/src/libgsmd/libgsmd.c
+++ b/src/libgsmd/libgsmd.c
@@ -64,7 +64,7 @@ static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)
 {
 	int rc;
 
-	if (!strcmp(device, LGSMD_DEVICE_GSMD)) {
+	if (!strncmp(device, LGSMD_DEVICE_GSMD, strlen(LGSMD_DEVICE_GSMD))) {
 		struct sockaddr_un sun;
 		
 		/* use unix domain socket to gsm daemon */
@@ -74,7 +74,8 @@ static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)
 		
 		memset(&sun, 0, sizeof(sun));
 		sun.sun_family = AF_UNIX;
-		memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
+		sun.sun_path[0] = '\0';
+		strncpy(sun.sun_path+1, device, sizeof(sun.sun_path)-1);
 
 		rc = connect(lh->fd, (struct sockaddr *)&sun, sizeof(sun));
 		if (rc < 0) {
@@ -184,6 +185,19 @@ struct lgsm_handle *lgsm_init(const char *device)
 	return lh;
 }
 
+struct lgsm_handle *lgsm_init_inst(unsigned int instance)
+{
+	struct lgsm_handle *lh = malloc(sizeof(*lh));
+	char buf[32];
+	if (instance == 0)
+		snprintf(buf, sizeof(buf), "gsmd");
+	else
+		snprintf(buf, sizeof(buf), "gsmd.%u", instance);
+
+	return lgsm_init(buf);
+}
+
+
 int lgsm_exit(struct lgsm_handle *lh)
 {
 	free(lh);
@@ -191,7 +205,6 @@ int lgsm_exit(struct lgsm_handle *lh)
 	return 0;
 }
 
-
 static u_int16_t next_msg_id;
 
 int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
diff --git a/src/util/libgsmd-tool.c b/src/util/libgsmd-tool.c
index 5fb1eca..4ef3df5 100644
--- a/src/util/libgsmd-tool.c
+++ b/src/util/libgsmd-tool.c
@@ -73,6 +73,7 @@ static int parse_mode(char *modestr)
 
 static struct option opts[] = {
 	{ "help", 0, 0, 'h' },
+	{ "instance", 1, 0, 'i' },
 	{ "version", 0, 0, 'V' },
 	{ "verbose", 0, 0, 'v' },
 	{ "mode", 1, 0, 'm' },
@@ -85,6 +86,7 @@ static void help(void)
 {
 	printf("Usage:\n"
 		"\t-h\t--help\tPrint this Help message\n"
+		"\t-i\t--instance <0-255>\tWhich instance nubmer to use\n"
 		"\t-V\t--version\tPrint version number\n"
 		"\t-v\t--verbose\tBe more verbose\n"
 		"\t-m\t--mode\tSet mode {shell,eventlog,atcmd}\n"
@@ -100,7 +102,7 @@ static void dump_version(void)
 int main(int argc, char **argv)
 {
 	char *pin = NULL;
-	int mode = MODE_NONE, shellwait = 0;
+	int mode = MODE_NONE, shellwait = 0, instance = 0;
 
 	printf("libgsm-tool - (C) 2006-2007 by Harald Welte and OpenMoko, Inc.\n"
 	       "              (C) 2012-2013 by Harald Welte\n"
@@ -108,7 +110,7 @@ int main(int argc, char **argv)
 
 	while (1) {
 		int c, option_index = 0;
-		c = getopt_long(argc, argv, "vVhwm:p:", opts, &option_index);
+		c = getopt_long(argc, argv, "vVhi:wm:p:", opts, &option_index);
 		if (c == -1)
 			break;
 
@@ -124,6 +126,9 @@ int main(int argc, char **argv)
 			help();
 			exit(0);
 			break;
+		case 'i':
+			instance = atoi(optarg);
+			break;
 		case 'm':
 			mode = parse_mode(optarg);
 			if (mode < 0) {
@@ -140,7 +145,7 @@ int main(int argc, char **argv)
 		}
 	}
 
-	lgsmh = lgsm_init(LGSMD_DEVICE_GSMD);
+	lgsmh = lgsm_init_inst(instance);
 	if (!lgsmh) {
 		fprintf(stderr, "Can't connect to gsmd\n");
 		exit(1);
-- 
cgit v1.2.3