diff -urN multipath-tools-0.1.2/ChangeLog multipath-tools-0.1.3/ChangeLog
--- multipath-tools-0.1.2/ChangeLog	2004-03-07 00:41:24.000000000 +0100
+++ multipath-tools-0.1.3/ChangeLog	2004-03-13 15:43:38.000000000 +0100
@@ -1,3 +1,11 @@
+2004-03-13 multipath-tools-0.1.3
+	* multipath config tool now has a config file parser
+	  (did I say I make the ugliest parsers ?)
+	* example multipath.conf to put in /etc (manualy)
+2004-03-12 multipath-tools-0.1.2
+	* detach the per devmap waiter threads
+	* set the thread stack size to lower limits
+	  (VSZ down to 4MB from 85 MB here)
 2004-03-06 multipath-tools-0.1.1
 	* include dlist.h in multipath main.c (PM Hahn)
 	* typo in hotplug script (PM Hahn)
diff -urN multipath-tools-0.1.2/multipath/Makefile multipath-tools-0.1.3/multipath/Makefile
--- multipath-tools-0.1.2/multipath/Makefile	2004-03-06 19:25:36.000000000 +0100
+++ multipath-tools-0.1.3/multipath/Makefile	2004-03-13 00:21:18.000000000 +0100
@@ -24,7 +24,7 @@
          -I$(klibcdir)/klibc/include -I$(klibcdir)/klibc/include/bits32 \
          -I$(GCCINCDIR) -I$(KERNEL_DIR)/include -I$(sysfsdir) -I. -I$(klibcarch)
 
-OBJS = devinfo.o main.o
+OBJS = configfile.o devinfo.o main.o
 CRT0 = $(klibcdir)/klibc/crt0.o
 LIB = $(klibcdir)/klibc/libc.a
 LIBGCC := $(shell $(CC) -print-libgcc-file-name )
diff -urN multipath-tools-0.1.2/multipath/configfile.c multipath-tools-0.1.3/multipath/configfile.c
--- multipath-tools-0.1.2/multipath/configfile.c	1970-01-01 01:00:00.000000000 +0100
+++ multipath-tools-0.1.3/multipath/configfile.c	2004-03-13 15:36:46.000000000 +0100
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "main.h"
+#include "configfile.h"
+
+#define CONFIG		"/etc/multipath.conf"
+#define MAXLINELENGHT	128
+#define MAXWORDLENGHT	32
+
+static int iscomment (char * line)
+{
+	char *p = line;
+
+	while (*p == ' ' && *p != EOF && *p != '\n')
+		p++;
+	
+	if (*p == '#' || *p == '!' || *p == ';' ||
+			 *p == EOF || *p == '\n')
+		return 1;
+
+	return 0;
+}
+
+static char * getword (char * word, char * line)
+{
+	char *p = line;
+	char *q;
+
+	memset (word, 0, MAXWORDLENGHT * sizeof (char));
+	while (*p != '"' && *p != EOF && *p != '\n')
+		p++;
+
+	if (*p == EOF || *p == '\n')
+		return (NULL);
+
+	q = ++p;
+	
+	if (*q == EOF || *q == '\n')
+		return (NULL);
+
+
+	while (*q != '"' && *q != EOF && *q != '\n')
+		q++;
+	
+	if (*q == EOF || *q == '\n')
+		return (NULL);
+
+	if (q -p > MAXWORDLENGHT)
+		return (NULL);
+
+	strncpy (word, p, q - p);
+
+	return (++q);
+}
+
+extern int check_config (void)
+{
+	struct stat buf;
+
+	if(stat(CONFIG, &buf) < 0)
+		return 0;
+
+	return 1;
+}
+
+extern void * read_config (void ** getuid)
+{
+	FILE *fp;
+	char *line;
+	char *word;
+	char *linep;
+	int i = 0;
+	struct hwentry * hwe = NULL;
+	struct hwentry * hw;
+
+	line = malloc (MAXLINELENGHT * sizeof (char));
+	word = malloc (MAXWORDLENGHT * sizeof (char));
+	hw = malloc (MAXHWENTRIES * sizeof (struct hwentry));
+	
+	fp = fopen (CONFIG, "r");
+
+	if (!fp) {
+		fprintf (stderr, "cannot fopen " CONFIG "\n");
+		return NULL;
+	}
+
+	
+
+	while (fgets (line, MAXLINELENGHT, fp))
+	{
+		if (iscomment (line))
+			continue;
+
+		hwe = &hw[i];
+		memset (hwe, 0, sizeof (struct hwentry));
+		linep = line;
+
+		linep = getword (word, linep);
+		if (linep == NULL)
+			return NULL;
+		
+		strncpy (hwe->vendor, word, 16);
+
+		linep = getword (word, linep);
+		if (linep == NULL)
+			return NULL;
+		
+		strncpy (hwe->product, word, 16);
+
+		linep = getword (word, linep);
+		if (linep == NULL)
+			return NULL;
+		
+		hwe->iopolicy = atoi (word);
+
+		if (hwe->iopolicy > HIGHESTPOLICY)
+			hwe->iopolicy = 0;
+
+		linep = getword (word, linep);
+		if (linep == NULL)
+			return NULL;
+		
+		hwe->getuid = getuid[atoi (word)];
+
+
+		if (++i > MAXHWENTRIES) {
+			hwe->getuid = NULL;
+			return NULL;
+		}
+	}
+	
+	/* terminate array */
+	hwe->getuid = NULL;
+	
+	fclose (fp);
+	free (line);
+	free (word);
+	
+	return hw;
+}
diff -urN multipath-tools-0.1.2/multipath/configfile.h multipath-tools-0.1.3/multipath/configfile.h
--- multipath-tools-0.1.2/multipath/configfile.h	1970-01-01 01:00:00.000000000 +0100
+++ multipath-tools-0.1.3/multipath/configfile.h	2004-03-13 13:45:59.000000000 +0100
@@ -0,0 +1,2 @@
+int check_config (void);
+void * read_config (void **);
diff -urN multipath-tools-0.1.2/multipath/main.c multipath-tools-0.1.3/multipath/main.c
--- multipath-tools-0.1.2/multipath/main.c	2004-03-06 19:26:01.000000000 +0100
+++ multipath-tools-0.1.3/multipath/main.c	2004-03-13 15:37:49.000000000 +0100
@@ -31,39 +31,40 @@
 #include "../libdevmapper/libdevmapper.h"
 #include "main.h"
 #include "devinfo.h"
+#include "configfile.h"
 
-/* White list switch */
+/* global default hardware list */
+struct hwentry defwlist[] = {
+	{"COMPAQ  ", "HSV110 (C)COMPAQ", GROUP_BY_TUR, &get_evpd_wwid},
+	{"COMPAQ  ", "MSA1000         ", GROUP_BY_TUR, &get_evpd_wwid},
+	{"COMPAQ  ", "MSA1000 VOLUME  ", GROUP_BY_TUR, &get_evpd_wwid},
+	{"DEC     ", "HSG80           ", GROUP_BY_TUR, &get_evpd_wwid},
+	{"HP      ", "HSV100          ", GROUP_BY_TUR, &get_evpd_wwid},
+	{"HP      ", "A6189A          ", MULTIBUS, &get_evpd_wwid},
+	{"HP      ", "OPEN-           ", MULTIBUS, &get_evpd_wwid},
+	{"DDN     ", "SAN DataDirector", MULTIBUS, &get_evpd_wwid},
+	{"FSC     ", "CentricStor     ", MULTIBUS, &get_evpd_wwid},
+	{"HITACHI ", "DF400           ", MULTIBUS, &get_evpd_wwid},
+	{"HITACHI ", "DF500           ", MULTIBUS, &get_evpd_wwid},
+	{"HITACHI ", "DF600           ", MULTIBUS, &get_evpd_wwid},
+	{"IBM     ", "ProFibre 4000R  ", MULTIBUS, &get_evpd_wwid},
+	{"SGI     ", "TP9100          ", MULTIBUS, &get_evpd_wwid},
+	{"SGI     ", "TP9300          ", MULTIBUS, &get_evpd_wwid},
+	{"SGI     ", "TP9400          ", MULTIBUS, &get_evpd_wwid},
+	{"SGI     ", "TP9500          ", MULTIBUS, &get_evpd_wwid},
+	{"", "", 0, NULL},
+};      
+        
+struct hwentry * wlist = &defwlist[0];
+
+void *getuid_list[] = {&get_evpd_wwid, NULL};
+        
 static int
-get_unique_id(struct path * mypath)
+get_path_tunables(struct path * mypath)
 {
 	int i;
-	static struct {
-		char * vendor;
-		char * product;
-		int iopolicy;
-		int (*getuid) (char *, char *);
-	} wlist[] = {
-		{"COMPAQ  ", "HSV110 (C)COMPAQ", GROUP_BY_TUR, &get_evpd_wwid},
-		{"COMPAQ  ", "MSA1000         ", GROUP_BY_TUR, &get_evpd_wwid},
-		{"COMPAQ  ", "MSA1000 VOLUME  ", GROUP_BY_TUR, &get_evpd_wwid},
-		{"DEC     ", "HSG80           ", GROUP_BY_TUR, &get_evpd_wwid},
-		{"HP      ", "HSV100          ", GROUP_BY_TUR, &get_evpd_wwid},
-		{"HP      ", "A6189A          ", MULTIBUS, &get_evpd_wwid},
-		{"HP      ", "OPEN-           ", MULTIBUS, &get_evpd_wwid},
-		{"DDN     ", "SAN DataDirector", MULTIBUS, &get_evpd_wwid},
-		{"FSC     ", "CentricStor     ", MULTIBUS, &get_evpd_wwid},
-		{"HITACHI ", "DF400           ", MULTIBUS, &get_evpd_wwid},
-		{"HITACHI ", "DF500           ", MULTIBUS, &get_evpd_wwid},
-		{"HITACHI ", "DF600           ", MULTIBUS, &get_evpd_wwid},
-		{"IBM     ", "ProFibre 4000R  ", MULTIBUS, &get_evpd_wwid},
-		{"SGI     ", "TP9100          ", MULTIBUS, &get_evpd_wwid},
-		{"SGI     ", "TP9300          ", MULTIBUS, &get_evpd_wwid},
-		{"SGI     ", "TP9400          ", MULTIBUS, &get_evpd_wwid},
-		{"SGI     ", "TP9500          ", MULTIBUS, &get_evpd_wwid},
-		{NULL, NULL, 0, NULL},
-	};
 
-	for (i = 0; wlist[i].vendor; i++) {
+	for (i = 0; wlist[i].getuid; i++) {
 		if (strncmp(mypath->vendor_id, wlist[i].vendor, 8) == 0 &&
 		    strncmp(mypath->product_id, wlist[i].product, 16) == 0) {
 			mypath->iopolicy = wlist[i].iopolicy;
@@ -171,8 +172,10 @@
 			curpath->sg_dev);
 	get_serial(curpath->serial, curpath->sg_dev);
 	curpath->tur = do_tur(curpath->sg_dev);
-	if (!get_unique_id(curpath))
+	if (!get_path_tunables(curpath)) {
+		fprintf (stderr, "get_path_tunables error\n");
 		return 1;
+	}
 
 	return 0;
 }
@@ -305,7 +308,7 @@
 				all_paths[k].rev,
 				all_paths[k].sg_dev);
 		get_serial(all_paths[k].serial, all_paths[k].sg_dev);
-		if (!get_unique_id(&all_paths[k]))
+		if (!get_path_tunables(&all_paths[k]))
 			continue;
 
 		if ((fd = open(all_paths[k].sg_dev, O_RDONLY)) < 0)
@@ -623,7 +626,7 @@
 
 	if ((all_paths[PINDEX(index,0)].iopolicy == MULTIBUS &&
 	    conf->iopolicy == -1) || conf->iopolicy == MULTIBUS) {
-		params_p += sprintf(params_p, " 1 %s %i %i",
+		params_p += sprintf(params_p, "1 %s %i %i",
 				    dm_ps_name, np, dm_ps_nr_args);
 		
 		for (i=0; i<=mp[index].npaths; i++) {
@@ -636,7 +639,7 @@
 
 	if ((all_paths[PINDEX(index,0)].iopolicy == FAILOVER &&
 	     conf->iopolicy == -1) || conf->iopolicy == FAILOVER) {
-		params_p += sprintf(params_p, " %i", mp[index].npaths + 1);
+		params_p += sprintf(params_p, "%i", mp[index].npaths + 1);
 		for (i=0; i<=mp[index].npaths; i++) {
 			if (0 != all_paths[PINDEX(index,i)].sg_id.scsi_type)
 				continue;
@@ -807,7 +810,7 @@
 	conf.dry_run = 0;	/* 1 == Do not Create/Update devmaps */
 	conf.verbose = 0;	/* 1 == Print all_paths and mp */
 	conf.quiet = 0;		/* 1 == Do not even print devmaps */
-	conf.iopolicy = -1;	/* Apply the defaults in get_unique_id() */
+	conf.iopolicy = -1;	/* do not override defaults */
 	conf.major = -1;
 	conf.minor = -1;
 
@@ -846,6 +849,10 @@
 			strncpy(conf.hotplugdev, argv[i], FILE_NAME_SIZE);
 	}
 
+	/* if we have a config file read it (overwrite wlist) */
+	if (check_config() && conf.iopolicy < 0)
+		wlist = read_config(getuid_list);
+
 	/* dynamic allocations */
 	mp = malloc(conf.max_devs * sizeof(struct multipath));
 	all_paths = malloc(conf.max_devs * sizeof(struct path));
diff -urN multipath-tools-0.1.2/multipath/main.h multipath-tools-0.1.3/multipath/main.h
--- multipath-tools-0.1.2/multipath/main.h	2004-03-05 13:51:44.000000000 +0100
+++ multipath-tools-0.1.3/multipath/main.h	2004-03-13 15:35:47.000000000 +0100
@@ -21,6 +21,7 @@
 
 /* local includes */
 #include "sg_include.h"
+#include "devinfo.h"
 
 /* exerpt from "sg_err.h" */
 #define SCSI_CHECK_CONDITION 	0x2
@@ -45,12 +46,14 @@
 #define PIDFILE		"/var/run/multipathd.pid"
 #define RUN		"/var/run/multipath.run"
 #define MAXTRY		50
+#define MAXHWENTRIES	100
 
-/* Storage controlers cpabilities */
+/* Storage controlers capabilities */
 #define FAILOVER	0
 #define MULTIBUS	1
 #define GROUP_BY_SERIAL	2
-#define GROUP_BY_TUR	4
+#define GROUP_BY_TUR	3
+#define HIGHESTPOLICY	3
 
 #define PINDEX(x,y)	mp[(x)].pindex[(y)]
 
@@ -113,6 +116,13 @@
 	char hotplugdev[FILE_NAME_SIZE];
 };
 
+struct hwentry {
+	char vendor[8];
+	char product[16];
+	int iopolicy;
+	int (*getuid) (char *, char *);
+};
+
 /* Build version */
 #define PROG    "multipath"
 
diff -urN multipath-tools-0.1.2/multipath/multipath.conf multipath-tools-0.1.3/multipath/multipath.conf
--- multipath-tools-0.1.2/multipath/multipath.conf	1970-01-01 01:00:00.000000000 +0100
+++ multipath-tools-0.1.3/multipath/multipath.conf	2004-03-13 15:39:47.000000000 +0100
@@ -0,0 +1,29 @@
+# "vendor", "product", "policy", "getuid fn"
+#
+# policy :
+# 0 FAILOVER
+# 1 MULTIBUS
+# 2 GROUP_BY_SERIAL
+# 3 GROUP_BY_TUR
+#
+# getuid :
+# 0 EVPD_WWID
+#
+"COMPAQ  ", "HSV110 (C)COMPAQ", "3", "0"
+"COMPAQ  ", "MSA1000         ", "3", "0"
+"COMPAQ  ", "MSA1000 VOLUME  ", "3", "0"
+"DEC     ", "HSG80           ", "3", "0"
+"HP      ", "HSV100          ", "3", "0"
+"HP      ", "A6189A          ", "3", "0"
+"HP      ", "OPEN-           ", "3", "0"
+"DDN     ", "SAN DataDirector", "3", "0"
+"FSC     ", "CentricStor     ", "3", "0"
+"HITACHI ", "DF400           ", "3", "0"
+"HITACHI ", "DF500           ", "3", "0"
+"HITACHI ", "DF600           ", "3", "0"
+"IBM     ", "ProFibre 4000R  ", "3", "0"
+"SGI     ", "TP9100          ", "3", "0"
+"SGI     ", "TP9300          ", "3", "0"
+"SGI     ", "TP9400          ", "3", "0"
+"SGI     ", "TP9500          ", "3", "0"
+
diff -urN multipath-tools-0.1.2/multipathd/main.c multipath-tools-0.1.3/multipathd/main.c
--- multipath-tools-0.1.2/multipathd/main.c	2004-03-12 11:51:46.000000000 +0100
+++ multipath-tools-0.1.3/multipathd/main.c	2004-03-12 23:14:21.000000000 +0100
@@ -3,7 +3,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <sys/resource.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
