diff -urN multipath-tools-0.1.3/ChangeLog multipath-tools-0.1.4/ChangeLog
--- multipath-tools-0.1.3/ChangeLog	2004-03-13 15:43:38.000000000 +0100
+++ multipath-tools-0.1.4/ChangeLog	2004-03-17 12:18:41.000000000 +0100
@@ -1,3 +1,11 @@
+2004-03-17 multipath-tools-0.1.4
+	* multipath clean up
+		* split default hw table in hwtable.h
+		* split grouping policies in pgpolocies.c
+		* pass *mp to setup_map instead of mp[]+index
+	* ensure defhwtable is used if /etc/multipath.conf is buggy
+	* hwtable is not global anymore
+	* unlink the runfile in various error paths
 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 ?)
diff -urN multipath-tools-0.1.3/multipath/Makefile multipath-tools-0.1.4/multipath/Makefile
--- multipath-tools-0.1.3/multipath/Makefile	2004-03-13 00:21:18.000000000 +0100
+++ multipath-tools-0.1.4/multipath/Makefile	2004-03-16 17:16:47.000000000 +0100
@@ -24,7 +24,8 @@
          -I$(klibcdir)/klibc/include -I$(klibcdir)/klibc/include/bits32 \
          -I$(GCCINCDIR) -I$(KERNEL_DIR)/include -I$(sysfsdir) -I. -I$(klibcarch)
 
-OBJS = configfile.o devinfo.o main.o
+OBJS = pgpolicies.o 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.3/multipath/configfile.c multipath-tools-0.1.4/multipath/configfile.c
--- multipath-tools-0.1.3/multipath/configfile.c	2004-03-13 15:36:46.000000000 +0100
+++ multipath-tools-0.1.4/multipath/configfile.c	2004-03-16 11:09:54.000000000 +0100
@@ -60,7 +60,7 @@
 {
 	struct stat buf;
 
-	if(stat(CONFIG, &buf) < 0)
+	if (stat (CONFIG, &buf) < 0)
 		return 0;
 
 	return 1;
diff -urN multipath-tools-0.1.3/multipath/hwtable.h multipath-tools-0.1.4/multipath/hwtable.h
--- multipath-tools-0.1.3/multipath/hwtable.h	1970-01-01 01:00:00.000000000 +0100
+++ multipath-tools-0.1.4/multipath/hwtable.h	2004-03-16 10:08:38.000000000 +0100
@@ -0,0 +1,22 @@
+#define setup_default_hwtable struct hwentry defhwtable[] = { \
+	{"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}, \
+}; \
+
+#define default_hwtable_addr &defhwtable[0]
diff -urN multipath-tools-0.1.3/multipath/main.c multipath-tools-0.1.4/multipath/main.c
--- multipath-tools-0.1.3/multipath/main.c	2004-03-13 15:37:49.000000000 +0100
+++ multipath-tools-0.1.4/multipath/main.c	2004-03-17 12:09:50.000000000 +0100
@@ -28,54 +28,21 @@
 #include <sys/ioctl.h>
 #include <dlist.h>
 #include <sysfs/libsysfs.h>
+
 #include "../libdevmapper/libdevmapper.h"
 #include "main.h"
 #include "devinfo.h"
 #include "configfile.h"
+#include "hwtable.h"
+#include "pgpolicies.h"
 
-/* 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];
+/* argv parser helper */
+#define argis(x) if (0 == strcmp (x, argv[i]))
 
+/* not nice */
 void *getuid_list[] = {&get_evpd_wwid, NULL};
         
 static int
-get_path_tunables(struct path * mypath)
-{
-	int 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;
-			if (!wlist[i].getuid(mypath->sg_dev, mypath->wwid))
-				return 0;
-		}
-	}
-	return 1;
-}
-
-static int
 sysfsdevice2devname (char *devname, char *device)
 {
 	char sysfs_path[FILE_NAME_SIZE];
@@ -83,19 +50,19 @@
 	char link_path[FILE_NAME_SIZE];
 	int r;
 
-	if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
-		fprintf(stderr, "[device] feature available with sysfs only\n");
+	if (sysfs_get_mnt_path (sysfs_path, FILE_NAME_SIZE)) {
+		fprintf (stderr, "[device] feature available with sysfs only\n");
 		exit (1);
 	}
 	
-	sprintf(link_path, "%s%s/block", sysfs_path, device);
+	sprintf (link_path, "%s%s/block", sysfs_path, device);
 	
-	r = sysfs_get_link(link_path, block_path, FILE_NAME_SIZE);
+	r = sysfs_get_link (link_path, block_path, FILE_NAME_SIZE);
 
 	if (r != 0)
 		return 1;
 
-	sysfs_get_name_from_path(block_path, devname, FILE_NAME_SIZE);
+	sysfs_get_name_from_path (block_path, devname, FILE_NAME_SIZE);
 
 	return 0;
 }
@@ -112,28 +79,28 @@
 	char attr_value[16];
 	char attr_ref_value[16];
 
-	if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
-		fprintf(stderr, "-D feature available with sysfs only\n");
+	if (sysfs_get_mnt_path (sysfs_path, FILE_NAME_SIZE)) {
+		fprintf (stderr, "-D feature available with sysfs only\n");
 		exit (1);
 	}
 		
-	sprintf(attr_ref_value, "%i:%i\n", major, minor);
-	sprintf(block_path, "%s/block", sysfs_path);
-	sdir = sysfs_open_directory(block_path);
-	sysfs_read_directory(sdir);
-
-	dlist_for_each_data(sdir->subdirs, devp, struct sysfs_directory) {
-		sprintf(attr_path, "%s/%s/dev", block_path, devp->name);
-		sysfs_read_attribute_value(attr_path, attr_value, 16);
-
-		if (!strcmp(attr_value, attr_ref_value)) {
-			sprintf(attr_path, "%s/%s", block_path, devp->name);
-			sysfs_get_name_from_path(attr_path, devname, FILE_NAME_SIZE);
+	sprintf (attr_ref_value, "%i:%i\n", major, minor);
+	sprintf (block_path, "%s/block", sysfs_path);
+	sdir = sysfs_open_directory (block_path);
+	sysfs_read_directory (sdir);
+
+	dlist_for_each_data (sdir->subdirs, devp, struct sysfs_directory) {
+		sprintf (attr_path, "%s/%s/dev", block_path, devp->name);
+		sysfs_read_attribute_value (attr_path, attr_value, 16);
+
+		if (!strcmp (attr_value, attr_ref_value)) {
+			sprintf (attr_path, "%s/%s", block_path, devp->name);
+			sysfs_get_name_from_path (attr_path, devname, FILE_NAME_SIZE);
 			break;
 		}
 	}
 
-	sysfs_close_directory(sdir);
+	sysfs_close_directory (sdir);
 	
 	return 0;
 }
@@ -157,24 +124,34 @@
 	};
 
 	for (i = 0; blist[i].lengh; i++) {
-		if (strncmp(dev, blist[i].headstr, blist[i].lengh) == 0)
+		if (strncmp (dev, blist[i].headstr, blist[i].lengh) == 0)
 			return 1;
 	}
 	return 0;
 }
 
 static int
-devinfo (struct path *curpath)
+devinfo (struct path *curpath, struct hwentry * hwtable)
 {
-	get_lun_strings(curpath->vendor_id,
+	int i;
+
+	get_lun_strings (curpath->vendor_id,
 			curpath->product_id,
 			curpath->rev,
 			curpath->sg_dev);
-	get_serial(curpath->serial, curpath->sg_dev);
-	curpath->tur = do_tur(curpath->sg_dev);
-	if (!get_path_tunables(curpath)) {
-		fprintf (stderr, "get_path_tunables error\n");
-		return 1;
+	
+	get_serial (curpath->serial, curpath->sg_dev);
+	curpath->tur = do_tur (curpath->sg_dev);
+
+	for (i = 0; hwtable[i].getuid; i++) {
+		if (strncmp (curpath->vendor_id, hwtable[i].vendor, 8) == 0 &&
+		    strncmp (curpath->product_id, hwtable[i].product, 16) == 0) {
+			
+			curpath->iopolicy = hwtable[i].iopolicy;
+
+			if (!hwtable[i].getuid (curpath->sg_dev, curpath->wwid))
+				return 1;
+		}
 	}
 
 	return 0;
@@ -182,7 +159,7 @@
 
 
 static int
-get_all_paths_sysfs(struct env * conf, struct path * all_paths)
+get_all_paths_sysfs (struct env * conf, struct path * all_paths)
 {
 	int k=0;
 	struct sysfs_directory * sdir;
@@ -194,57 +171,57 @@
 	char path[FILE_NAME_SIZE];
 	struct path curpath;
 
-	memset(empty_buff, 0, WWID_SIZE);
-	memset(refwwid, 0, WWID_SIZE);
+	memset (empty_buff, 0, WWID_SIZE);
+	memset (refwwid, 0, WWID_SIZE);
 
 	/* if called from hotplug, only consider the paths that relate
 	   to the device pointed by conf.hotplugdev */
 
-	if (strncmp("/devices", conf->hotplugdev, 8) == 0) {
+	if (strncmp ("/devices", conf->hotplugdev, 8) == 0) {
 		if (sysfsdevice2devname (buff, conf->hotplugdev))
 			return 0;
 
-		sprintf(curpath.sg_dev, "/dev/%s", buff);
+		sprintf (curpath.sg_dev, "/dev/%s", buff);
 
-		if (devinfo(&curpath))
+		if (devinfo (&curpath, conf->hwtable))
 			return 0;
 
-		strcpy(refwwid, curpath.wwid);
-		memset(&curpath, 0, sizeof(path));
+		strcpy (refwwid, curpath.wwid);
+		memset (&curpath, 0, sizeof (path));
 	}
 
 	/* if major/minor specified on the cmd line,
 	   only consider affiliated paths */
 
 	if (conf->major >= 0 && conf->minor >= 0) {
-		if (devt2devname(buff, conf->major, conf->minor))
+		if (devt2devname (buff, conf->major, conf->minor))
 			return 0;
 		
-		sprintf(curpath.sg_dev, "/dev/%s", buff);
+		sprintf (curpath.sg_dev, "/dev/%s", buff);
 
-		if (devinfo(&curpath))
+		if (devinfo (&curpath, conf->hwtable))
 			return 0;
 
-		strcpy(refwwid, curpath.wwid);
-		memset(&curpath, 0, sizeof(path));
+		strcpy (refwwid, curpath.wwid);
+		memset (&curpath, 0, sizeof (path));
 	}
 		
 
-	sprintf(path, "%s/block", conf->sysfs_path);
-	sdir = sysfs_open_directory(path);
-	sysfs_read_directory(sdir);
+	sprintf (path, "%s/block", conf->sysfs_path);
+	sdir = sysfs_open_directory (path);
+	sysfs_read_directory (sdir);
 
-	dlist_for_each_data(sdir->subdirs, devp, struct sysfs_directory) {
-		if (blacklist(devp->name))
+	dlist_for_each_data (sdir->subdirs, devp, struct sysfs_directory) {
+		if (blacklist (devp->name))
 			continue;
 
-		sysfs_read_directory(devp);
+		sysfs_read_directory (devp);
 
-		if(devp->links == NULL)
+		if (devp->links == NULL)
 			continue;
 
-		dlist_for_each_data(devp->links, linkp, struct sysfs_link) {
-			if (!strncmp(linkp->name, "device", 6))
+		dlist_for_each_data (devp->links, linkp, struct sysfs_link) {
+			if (!strncmp (linkp->name, "device", 6))
 				break;
 		}
 
@@ -252,45 +229,45 @@
 			continue;
 		}
 
-		basename(devp->path, buff);
-		sprintf(curpath.sg_dev, "/dev/%s", buff);
+		basename (devp->path, buff);
+		sprintf (curpath.sg_dev, "/dev/%s", buff);
 
-		if(devinfo(&curpath)) {
-			memset(&curpath, 0, sizeof(path));
+		if (devinfo (&curpath, conf->hwtable)) {
+			memset (&curpath, 0, sizeof (path));
 			continue;
 		}
 
-		if (memcmp(empty_buff, refwwid, WWID_SIZE) != 0 && 
-		    strncmp(curpath.wwid, refwwid, WWID_SIZE) != 0) {
-			memset(&curpath, 0, sizeof(path));
+		if (memcmp (empty_buff, refwwid, WWID_SIZE) != 0 && 
+		    strncmp (curpath.wwid, refwwid, WWID_SIZE) != 0) {
+			memset (&curpath, 0, sizeof (path));
 			continue;
 		}
 
-		strcpy(all_paths[k].sg_dev, curpath.sg_dev);
-		strcpy(all_paths[k].dev, curpath.sg_dev);
-		strcpy(all_paths[k].wwid, curpath.wwid);
-		strcpy(all_paths[k].vendor_id, curpath.vendor_id);
-		strcpy(all_paths[k].product_id, curpath.product_id);
+		strcpy (all_paths[k].sg_dev, curpath.sg_dev);
+		strcpy (all_paths[k].dev, curpath.sg_dev);
+		strcpy (all_paths[k].wwid, curpath.wwid);
+		strcpy (all_paths[k].vendor_id, curpath.vendor_id);
+		strcpy (all_paths[k].product_id, curpath.product_id);
 		all_paths[k].iopolicy = curpath.iopolicy;
 		all_paths[k].tur = curpath.tur;
 
 		/* done with curpath, zero for reuse */
-		memset(&curpath, 0, sizeof(path));
+		memset (&curpath, 0, sizeof (path));
 
-		basename(linkp->target, buff);
-		sscanf(buff, "%i:%i:%i:%i",
+		basename (linkp->target, buff);
+		sscanf (buff, "%i:%i:%i:%i",
 			&all_paths[k].sg_id.host_no,
 			&all_paths[k].sg_id.channel,
 			&all_paths[k].sg_id.scsi_id,
 			&all_paths[k].sg_id.lun);
 		k++;
 	}
-	sysfs_close_directory(sdir);
+	sysfs_close_directory (sdir);
 	return 0;
 }
 
 static int
-get_all_paths_nosysfs(struct env * conf, struct path * all_paths,
+get_all_paths_nosysfs (struct env * conf, struct path * all_paths,
 		      struct scsi_dev * all_scsi_ids)
 {
 	int k, i, fd;
@@ -298,27 +275,21 @@
 	char file_name[FILE_NAME_SIZE];
 
 	for (k = 0; k < conf->max_devs; k++) {
-		strcpy(file_name, "/dev/sg");
-		sprintf(buff, "%d", k);
-		strncat(file_name, buff, FILE_NAME_SIZE);
-		strcpy(all_paths[k].sg_dev, file_name);
-
-		get_lun_strings(all_paths[k].vendor_id,
-				all_paths[k].product_id,
-				all_paths[k].rev,
-				all_paths[k].sg_dev);
-		get_serial(all_paths[k].serial, all_paths[k].sg_dev);
-		if (!get_path_tunables(&all_paths[k]))
-			continue;
+		strcpy (file_name, "/dev/sg");
+		sprintf (buff, "%d", k);
+		strncat (file_name, buff, FILE_NAME_SIZE);
+		strcpy (all_paths[k].sg_dev, file_name);
 
-		if ((fd = open(all_paths[k].sg_dev, O_RDONLY)) < 0)
+		devinfo (&all_paths[k], conf->hwtable);
+
+		if ((fd = open (all_paths[k].sg_dev, O_RDONLY)) < 0)
 			return 0;
 
-		if (0 > ioctl(fd, SG_GET_SCSI_ID, &(all_paths[k].sg_id)))
-			printf("device %s failed on sg ioctl, skip\n",
+		if (0 > ioctl (fd, SG_GET_SCSI_ID, &(all_paths[k].sg_id)))
+			printf ("device %s failed on sg ioctl, skip\n",
 			       file_name);
 
-		close(fd);
+		close (fd);
 
 		for (i = 0; i < conf->max_devs; i++) {
 			if ((all_paths[k].sg_id.host_no ==
@@ -330,7 +301,7 @@
 			    && (all_paths[k].sg_id.channel ==
 				((all_scsi_ids[i].scsi_id.
 				  dev_id >> 16) & 0xff))) {
-				strcpy(all_paths[k].dev, all_scsi_ids[i].dev);
+				strcpy (all_paths[k].dev, all_scsi_ids[i].dev);
 				break;
 			}
 		}
@@ -339,7 +310,7 @@
 }
 
 static int
-get_all_scsi_ids(struct env * conf, struct scsi_dev * all_scsi_ids)
+get_all_scsi_ids (struct env * conf, struct scsi_dev * all_scsi_ids)
 {
 	int k, big, little, res, host_no, fd;
 	char buff[64];
@@ -347,11 +318,11 @@
 	struct scsi_idlun my_scsi_id;
 
 	for (k = 0; k < conf->max_devs; k++) {
-		strcpy(fname, "/dev/sd");
+		strcpy (fname, "/dev/sd");
 		if (k < 26) {
 			buff[0] = 'a' + (char) k;
 			buff[1] = '\0';
-			strcat(fname, buff);
+			strcat (fname, buff);
 		} else if (k <= 255) {
 			/* assumes sequence goes x,y,z,aa,ab,ac etc */
 			big = k / 26;
@@ -361,34 +332,34 @@
 			buff[0] = 'a' + (char) big;
 			buff[1] = 'a' + (char) little;
 			buff[2] = '\0';
-			strcat(fname, buff);
+			strcat (fname, buff);
 		} else
-			strcat(fname, "xxxx");
+			strcat (fname, "xxxx");
 
-		if ((fd = open(fname, O_RDONLY)) < 0) {
+		if ((fd = open (fname, O_RDONLY)) < 0) {
 			if (conf->verbose)
-				fprintf(stderr, "can't open %s. mknod ?",
+				fprintf (stderr, "can't open %s. mknod ?",
 					fname); 
 			continue;
 		}
 
-		res = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &my_scsi_id);
+		res = ioctl (fd, SCSI_IOCTL_GET_IDLUN, &my_scsi_id);
 		if (res < 0) {
-			close(fd);
-			printf("Could not get scsi idlun\n");
+			close (fd);
+			printf ("Could not get scsi idlun\n");
 			continue;
 		}
 
-		res = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
+		res = ioctl (fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
 		if (res < 0) {
-			close(fd);
-			printf("Could not get host_no\n");
+			close (fd);
+			printf ("Could not get host_no\n");
 			continue;
 		}
 
-		close(fd);
+		close (fd);
 
-		strcpy(all_scsi_ids[k].dev, fname);
+		strcpy (all_scsi_ids[k].dev, fname);
 		all_scsi_ids[k].scsi_id = my_scsi_id;
 		all_scsi_ids[k].host_no = host_no;
 	}
@@ -400,50 +371,65 @@
 #define NOWWID	1
 
 static void
-print_path(struct path * all_paths, int k, int style)
+print_path (struct path * all_paths, int k, int style)
 {
 	if (style != NOWWID)
-		printf("%s ", all_paths[k].wwid);
+		printf ("%s ", all_paths[k].wwid);
 	else
-		printf(" \\_");
-	printf("(%i %i %i %i) ",
+		printf (" \\_");
+
+	printf ("(%i %i %i %i) ",
 	       all_paths[k].sg_id.host_no,
 	       all_paths[k].sg_id.channel,
-	       all_paths[k].sg_id.scsi_id, all_paths[k].sg_id.lun);
-	if(0 != strcmp(all_paths[k].sg_dev, all_paths[k].dev))
-		printf("%s ", all_paths[k].sg_dev);
-	printf("%s ", all_paths[k].dev);
-	printf("[%.16s]\n", all_paths[k].product_id);
+	       all_paths[k].sg_id.scsi_id,
+	       all_paths[k].sg_id.lun);
+
+	/* for 2.4 kernels, sg_dev should be printed */
+	if (0 != strcmp (all_paths[k].sg_dev, all_paths[k].dev))
+		printf ("%s ", all_paths[k].sg_dev);
+
+	printf ("%s ", all_paths[k].dev);
+	printf ("[%.16s]\n", all_paths[k].product_id);
 }
 
 static void
-print_all_path(struct env * conf, struct path * all_paths)
+print_all_path (struct env * conf, struct path * all_paths)
 {
 	int k;
 	char empty_buff[WWID_SIZE];
 
-	memset(empty_buff, 0, WWID_SIZE);
+	/* initialize a cmp 0-filled buffer */
+	memset (empty_buff, 0, WWID_SIZE);
+
+	fprintf (stdout, "# all paths :\n");
+
 	for (k = 0; k < conf->max_devs; k++) {
-		if (memcmp(empty_buff, all_paths[k].wwid, WWID_SIZE) == 0)
+		
+		/* leave out paths with incomplete devinfo */
+		if (memcmp (empty_buff, all_paths[k].wwid, WWID_SIZE) == 0)
 			continue;
-		print_path(all_paths, k, ALL);
+
+		print_path (all_paths, k, ALL);
 	}
 }
 
 static void
-print_all_mp(struct path * all_paths, struct multipath * mp, int nmp)
+print_all_mp (struct path * all_paths, struct multipath * mp, int nmp)
 {
 	int k, i;
 
+	fprintf (stdout, "# all multipaths :\n");
+
 	for (k = 0; k <= nmp; k++) {
-		printf("%s\n", mp[k].wwid);
+		printf ("%s\n", mp[k].wwid);
+
 		for (i = 0; i <= mp[k].npaths; i++)
-			print_path(all_paths, PINDEX(k,i), NOWWID);
+			print_path (all_paths, PINDEX(k,i), NOWWID);
 	}
 }
 
 static int
-coalesce_paths(struct env * conf, struct multipath * mp,
+coalesce_paths (struct env * conf, struct multipath * mp,
 	       struct path * all_paths)
 {
 	int k, i, nmp, np, already_done;
@@ -451,18 +437,18 @@
 
 	nmp = -1;
 	already_done = 0;
-	memset(empty_buff, 0, WWID_SIZE);
+	memset (empty_buff, 0, WWID_SIZE);
 
 	for (k = 0; k < conf->max_devs - 1; k++) {
 		/* skip this path for some reason */
 
 		/* 1. if path has no unique id */
-		if (memcmp(empty_buff, all_paths[k].wwid, WWID_SIZE) == 0)
+		if (memcmp (empty_buff, all_paths[k].wwid, WWID_SIZE) == 0)
 			continue;
 
 		/* 2. if mp with this uid already instanciated */
 		for (i = 0; i <= nmp; i++) {
-			if (0 == strcmp(mp[i].wwid, all_paths[k].wwid))
+			if (0 == strcmp (mp[i].wwid, all_paths[k].wwid))
 				already_done = 1;
 		}
 		if (already_done) {
@@ -473,14 +459,14 @@
 		/* at this point, we know we really got a new mp */
 		np = 0;
 		nmp++;
-		strcpy(mp[nmp].wwid, all_paths[k].wwid);
+		strcpy (mp[nmp].wwid, all_paths[k].wwid);
 		PINDEX(nmp,np) = k;
 
 		if (mp[nmp].size == 0)
-			mp[nmp].size = get_disk_size(all_paths[k].dev);
+			mp[nmp].size = get_disk_size (all_paths[k].dev);
 
 		for (i = k + 1; i < conf->max_devs; i++) {
-			if (0 == strcmp(all_paths[k].wwid, all_paths[i].wwid)) {
+			if (0 == strcmp (all_paths[k].wwid, all_paths[i].wwid)) {
 				np++;
 				PINDEX(nmp,np) = i;
 				mp[nmp].npaths = np;
@@ -490,216 +476,115 @@
 	return nmp;
 }
 
-static void
-group_by_tur(struct multipath * mp, struct path * all_paths, char * str) {
-	int left_path_count = 0;
-	int right_path_count = 0;
-	int i;
-	char left_path_buff[FILE_NAME_SIZE], right_path_buff[FILE_NAME_SIZE];
-	char * left_path_buff_p = &left_path_buff[0];
-	char * right_path_buff_p = &right_path_buff[0];
-
-	for (i = 0; i <= mp->npaths; i++) {
-		if (all_paths[mp->pindex[i]].tur) {
-			left_path_buff_p += sprintf(left_path_buff_p, " %s", all_paths[mp->pindex[i]].dev);
-			left_path_count++;
-		} else {
-			right_path_buff_p += sprintf(right_path_buff_p, " %s", all_paths[mp->pindex[i]].dev);
-			right_path_count++;
-		}
-	}
-	if (!left_path_count)
-		sprintf(str, " 1 round-robin %i 0 %s", right_path_count, right_path_buff);
-	else if (!right_path_count)
-		sprintf(str, " 1 round-robin %i 0 %s", left_path_count, left_path_buff);
-	else
-		sprintf(str, " 2 round-robin %i 0 %s round-robin %i 0 %s",
-			left_path_count, left_path_buff,
-			right_path_count, right_path_buff);
-}
-
-static void
-group_by_serial(struct multipath * mp, struct path * all_paths, char * str) {
-	int path_count, pg_count = 0;
-	int i, k;
-	int * bitmap;
-	char path_buff[FILE_NAME_SIZE];
-	char pg_buff[FILE_NAME_SIZE];
-	char * path_buff_p = &path_buff[0];
-	char * pg_buff_p = &pg_buff[0];
-
-	/* init the bitmap */
-	bitmap = malloc((mp->npaths + 1) * sizeof(int));
-	memset(bitmap, 0, (mp->npaths + 1) * sizeof(int));
-
-	for (i = 0; i <= mp->npaths; i++) {
-		if (bitmap[i])
-			continue;
-
-		/* here, we really got a new pg */
-		pg_count++;
-		path_count = 1;
-		memset(&path_buff, 0, FILE_NAME_SIZE * sizeof(char));
-		path_buff_p = &path_buff[0];
-
-		path_buff_p += sprintf(path_buff_p, " %s", all_paths[mp->pindex[i]].dev);
-		bitmap[i] = 1;
-
-		for (k = i + 1; k <= mp->npaths; k++) {
-			if (bitmap[k])
-				continue;
-			if (0 == strcmp(all_paths[mp->pindex[i]].serial,
-					all_paths[mp->pindex[k]].serial)) {
-				path_buff_p += sprintf(path_buff_p, " %s", all_paths[mp->pindex[k]].dev);
-				bitmap[k] = 1;
-				path_count++;
-			}
-		}
-		pg_buff_p += sprintf(pg_buff_p, " round-robin %i 0%s",
-				     path_count, path_buff);
-	}
-	sprintf(str, " %i%s", pg_count, pg_buff);
-	free(bitmap);
-}
-
 static int
-dm_simplecmd(int task, const char *name) {
+dm_simplecmd (int task, const char *name) {
 	int r = 0;
 	struct dm_task *dmt;
 
-	if (!(dmt = dm_task_create(task)))
+	if (!(dmt = dm_task_create (task)))
 		return 0;
 
-	if (!dm_task_set_name(dmt, name))
+	if (!dm_task_set_name (dmt, name))
 		goto out;
 
-	r = dm_task_run(dmt);
+	r = dm_task_run (dmt);
 
 	out:
-		dm_task_destroy(dmt);
+		dm_task_destroy (dmt);
 		return r;
 }
 
 static int
-dm_addmap(int task, const char *name, const char *params, long size) {
+dm_addmap (int task, const char *name, const char *params, long size) {
 	struct dm_task *dmt;
 
-	if (!(dmt = dm_task_create(task)))
+	if (!(dmt = dm_task_create (task)))
 		return 0;
 
-	if (!dm_task_set_name(dmt, name))
+	if (!dm_task_set_name (dmt, name))
 		goto addout;
 
-	if (!dm_task_add_target(dmt, 0, size, DM_TARGET, params))
+	if (!dm_task_add_target (dmt, 0, size, DM_TARGET, params))
 		goto addout;
 
-	if (!dm_task_run(dmt))
+	if (!dm_task_run (dmt))
 		goto addout;
 
 	addout:
-	dm_task_destroy(dmt);
+	dm_task_destroy (dmt);
 	return 1;
 }
 
+/* helper for grouping policy selection */
+
+#define policyis(x) (all_paths[mp->pindex[0]].iopolicy == x && conf->iopolicy == -1) \
+		    || conf->iopolicy == x
+
 static int
-setup_map(struct env * conf, struct path * all_paths,
-	struct multipath * mp, int index, int op)
+setup_map (struct env * conf, struct path * all_paths,
+	struct multipath * mp, int op)
 {
 	char params[255];
 	char * params_p;
-	int i, np;
-
-	/* defaults for multipath target */
-	char * dm_ps_name           = "round-robin";
-	int dm_ps_nr_args           = 0;
 
 	params_p = &params[0];
 
-	np = 0;
-	for (i=0; i<=mp[index].npaths; i++) {
-		if (0 == all_paths[PINDEX(index,i)].sg_id.scsi_type)
-			np++;
-	}
+	/* paths grouping policy selector */
+	/* implementations in pgpolicies.c */
 
-	if (np < 1)
-		return 0;
+	if (policyis (MULTIBUS))
+		one_group (mp, all_paths, params_p);
 
-	if ((all_paths[PINDEX(index,0)].iopolicy == MULTIBUS &&
-	    conf->iopolicy == -1) || conf->iopolicy == MULTIBUS) {
-		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++) {
-			if (0 != all_paths[PINDEX(index,i)].sg_id.scsi_type)
-				continue;
-			params_p += sprintf(params_p, " %s",
-					    all_paths[PINDEX(index,i)].dev);
-		}
-	}
+	if (policyis (FAILOVER))
+		one_path_per_group (mp, all_paths, params_p);
 
-	if ((all_paths[PINDEX(index,0)].iopolicy == FAILOVER &&
-	     conf->iopolicy == -1) || conf->iopolicy == FAILOVER) {
-		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;
-			params_p += sprintf(params_p, " %s ",
-					    dm_ps_name);
-			params_p += sprintf(params_p, "1 %i",
-					    dm_ps_nr_args);
-			params_p += sprintf(params_p, " %s",
-					    all_paths[PINDEX(index,i)].dev);
-		}
-	}
+	if (policyis (GROUP_BY_SERIAL))
+		group_by_serial (mp, all_paths, params_p);
 
-	if ((all_paths[PINDEX(index,0)].iopolicy == GROUP_BY_SERIAL &&
-	     conf->iopolicy == -1) || conf->iopolicy == GROUP_BY_SERIAL) {
-		group_by_serial(&mp[index], all_paths, params_p);
-	}
-
-	if ((all_paths[PINDEX(index,0)].iopolicy == GROUP_BY_TUR &&
-	     conf->iopolicy == -1) || conf->iopolicy == GROUP_BY_TUR) {
-		group_by_tur(&mp[index], all_paths, params_p);
-	}
+	if (policyis (GROUP_BY_TUR))
+		group_by_tur (mp, all_paths, params_p);
 
-	if (mp[index].size < 0)
+	if (mp->size < 0)
 		return 0;
 
 	if (!conf->quiet) {
+
 		if (op == DM_DEVICE_RELOAD)
-			printf("U:");
+			printf ("U:");
+
 		if (op == DM_DEVICE_CREATE)
-			printf("N:");
-		printf("%s:0 %li %s %s\n",
-			mp[index].wwid, mp[index].size, DM_TARGET, params);
+			printf ("N:");
+
+		printf ("%s:0 %li %s%s\n",
+			mp->wwid, mp->size, DM_TARGET, params);
 	}
 
 	if (op == DM_DEVICE_RELOAD)
-		dm_simplecmd(DM_DEVICE_SUSPEND, mp[index].wwid);
+		dm_simplecmd (DM_DEVICE_SUSPEND, mp->wwid);
 
-	dm_addmap(op, mp[index].wwid, params, mp[index].size);
+	dm_addmap (op, mp->wwid, params, mp->size);
 
 	if (op == DM_DEVICE_RELOAD)
-		dm_simplecmd(DM_DEVICE_RESUME, mp[index].wwid);
+		dm_simplecmd (DM_DEVICE_RESUME, mp->wwid);
 
 	return 1;
 }
 
 static int
-map_present(char * str)
+map_present (char * str)
 {
         int r = 0;
 	struct dm_task *dmt;
         struct dm_names *names;
         unsigned next = 0;
 
-	if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+	if (!(dmt = dm_task_create (DM_DEVICE_LIST)))
 		return 0;
 
-	if (!dm_task_run(dmt))
+	if (!dm_task_run (dmt))
 		goto out;
 
-	if (!(names = dm_task_get_names(dmt)))
+	if (!(names = dm_task_get_names (dmt)))
 		goto out;
 
 	if (!names->dev) {
@@ -707,14 +592,14 @@
 	}
 
 	do {
-		if (0 == strcmp(names->name, str))
+		if (0 == strcmp (names->name, str))
 			r = 1;
 		next = names->next;
 		names = (void *) names + next;
 	} while (next);
 
 	out:
-	dm_task_destroy(dmt);
+	dm_task_destroy (dmt);
 	return r;
 }
 
@@ -730,7 +615,7 @@
 	file = fopen (PIDFILE, "r");
 
 	if (!file) {
-		fprintf(stderr, "cannot signal daemon, pidfile not found\n");
+		fprintf (stderr, "cannot signal daemon, pidfile not found\n");
 		return;
 	}
 
@@ -740,25 +625,25 @@
 	pid = (pid_t) atol (buf);
 	free (buf);
 
-	kill(pid, SIGHUP);
+	kill (pid, SIGHUP);
 }
 
 static int
-filepresent(char * run) {
+filepresent (char * run) {
 	struct stat buf;
 
-	if(!stat(run, &buf))
+	if(!stat (run, &buf))
 		return 1;
 	return 0;
 }
 
 static void
-usage(char * progname)
+usage (char * progname)
 {
-	fprintf(stderr, VERSION_STRING);
-	fprintf(stderr, "Usage: %s [-v|-q] [-d] [-m max_devs]\n",
+	fprintf (stderr, VERSION_STRING);
+	fprintf (stderr, "Usage: %s [-v|-q] [-d] [-m max_devs]\n",
 		progname);
-	fprintf(stderr,	"                   [-p failover|multibus|group_by_serial]\n" \
+	fprintf (stderr,	"                   [-p failover|multibus|group_by_serial]\n" \
 			"                   [device]\n" \
 			"\n" \
 			"\t-v\t\tverbose, print all paths and multipaths\n" \
@@ -777,11 +662,13 @@
 			"\tdevice\t\tlimit scope to the device's multipath\n" \
 			"\t\t\t(hotplug-style $DEVPATH reference)\n"
 		);
-	exit(1);
+
+	unlink (RUN);
+	exit (1);
 }
 
 int
-main(int argc, char *argv[])
+main (int argc, char *argv[])
 {
 	struct multipath * mp;
 	struct path * all_paths;
@@ -791,17 +678,17 @@
 	int try = 0;
 
 	/* Don't run in parallel */
-	while (filepresent(RUN) && try++ < MAXTRY)
-		usleep(100000);
+	while (filepresent (RUN) && try++ < MAXTRY)
+		usleep (100000);
 
-	if (filepresent(RUN)) {
-		fprintf(stderr, "waited for to long. exiting\n");
+	if (filepresent (RUN)) {
+		fprintf (stderr, "waited for to long. exiting\n");
 		exit (1);
 	}
 	
 	/* Our turn */
-	if (!open(RUN, O_CREAT)) {
-		fprintf(stderr, "can't create runfile\n");
+	if (!open (RUN, O_CREAT)) {
+		fprintf (stderr, "can't create runfile\n");
 		exit (1);
 	}
 		
@@ -813,90 +700,124 @@
 	conf.iopolicy = -1;	/* do not override defaults */
 	conf.major = -1;
 	conf.minor = -1;
+	conf.hwtable = NULL;
 
+	/* argv parser */
 	for (i = 1; i < argc; ++i) {
-		if (0 == strcmp("-v", argv[i])) {
+
+		argis ("-v") {
 			if (conf.quiet == 1)
-				usage(argv[0]);
+				usage (argv[0]);
 			conf.verbose = 1;
-		} else if (0 == strcmp("-m", argv[i])) {
-			conf.max_devs = atoi(argv[++i]);
+		}
+		
+		else argis ("-m") {
+			conf.max_devs = atoi (argv[++i]);
 			if (conf.max_devs < 2)
-				usage(argv[0]);
-		} else if (0 == strcmp("-D", argv[i])) {
-			conf.major = atoi(argv[++i]);
-			conf.minor = atoi(argv[++i]);
-		} else if (0 == strcmp("-q", argv[i])) {
+				usage (argv[0]);
+		}
+		
+		else argis ("-D") {
+			conf.major = atoi (argv[++i]);
+			conf.minor = atoi (argv[++i]);
+		}
+		
+		else argis ("-q") {
 			if (conf.verbose == 1)
-				usage(argv[0]);
+				usage (argv[0]);
 			conf.quiet = 1;
-		} else if (0 == strcmp("-d", argv[i]))
+		}
+		
+		else argis ("-d")
 			conf.dry_run = 1;
-		else if (0 == strcmp("-p", argv[i])) {
+		
+		else argis ("-p") {
 			i++;
-			if (!strcmp(argv[i], "failover"))
+			argis ("failover")
 				conf.iopolicy = FAILOVER;
-			if (!strcmp(argv[i], "multibus"))
+			
+			argis ("multibus")
 				conf.iopolicy = MULTIBUS;
-			if (!strcmp(argv[i], "group_by_serial"))
+
+			argis ("group_by_serial")
 				conf.iopolicy = GROUP_BY_SERIAL;
-			if (!strcmp(argv[i], "group_by_tur"))
+
+			argis ("group_by_tur")
 				conf.iopolicy = GROUP_BY_TUR;
-		} else if (*argv[i] == '-') {
-			fprintf(stderr, "Unknown switch: %s\n", argv[i]);
-			usage(argv[0]);
+		}
+		
+		else if (*argv[i] == '-') {
+			fprintf (stderr, "Unknown switch: %s\n", argv[i]);
+			usage (argv[0]);
 		} else
-			strncpy(conf.hotplugdev, argv[i], FILE_NAME_SIZE);
+			strncpy (conf.hotplugdev, argv[i], FILE_NAME_SIZE);
+	}
+
+	/* if we have a config file read it (overwrite hwtable) */
+	if (check_config () && conf.iopolicy < 0) {
+		conf.hwtable = read_config (getuid_list);
+
+		/* read_config went nuts, fall back to defaults */
+		if (conf.hwtable == NULL) {
+			setup_default_hwtable;
+			conf.hwtable = default_hwtable_addr;
+		}
+
+	} else {
+		setup_default_hwtable;
+		conf.hwtable = default_hwtable_addr;
 	}
 
-	/* 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));
-	all_scsi_ids = malloc(conf.max_devs * sizeof(struct scsi_dev));
+	mp = malloc (conf.max_devs * sizeof (struct multipath));
+	all_paths = malloc (conf.max_devs * sizeof (struct path));
+	all_scsi_ids = malloc (conf.max_devs * sizeof (struct scsi_dev));
+
 	if (mp == NULL || all_paths == NULL || all_scsi_ids == NULL)
-		exit(1);
+		exit (1);
 
-	if (sysfs_get_mnt_path(conf.sysfs_path, FILE_NAME_SIZE)) {
-		get_all_scsi_ids(&conf, all_scsi_ids);
-		get_all_paths_nosysfs(&conf, all_paths, all_scsi_ids);
+	if (sysfs_get_mnt_path (conf.sysfs_path, FILE_NAME_SIZE)) {
+		get_all_scsi_ids (&conf, all_scsi_ids);
+		get_all_paths_nosysfs (&conf, all_paths, all_scsi_ids);
 	} else {
-		get_all_paths_sysfs(&conf, all_paths);
+		get_all_paths_sysfs (&conf, all_paths);
 	}
 
-	nmp = coalesce_paths(&conf, mp, all_paths);
+	nmp = coalesce_paths (&conf, mp, all_paths);
 
 	if (conf.verbose) {
-		print_all_path(&conf, all_paths);
-		fprintf(stdout, "\n");
-		print_all_mp(all_paths, mp, nmp);
-		fprintf(stdout, "\n");
+		print_all_path (&conf, all_paths);
+		print_all_mp (all_paths, mp, nmp);
+	}
+
+	/* last chance to quit before messing with devmaps */
+	if (conf.dry_run) {
+		unlink (RUN);
+		exit (0);
 	}
 
-	if (conf.dry_run)
-		exit(0);
+	if (conf.verbose)
+		fprintf (stdout, "# device maps :\n");
 
 	for (k=0; k<=nmp; k++) {
-		if (map_present(mp[k].wwid)) {
-			setup_map(&conf, all_paths, mp, k, DM_DEVICE_RELOAD);
+		if (map_present (mp[k].wwid)) {
+			setup_map (&conf, all_paths, &mp[k], DM_DEVICE_RELOAD);
 		} else {
-			setup_map(&conf, all_paths, mp, k, DM_DEVICE_CREATE);
+			setup_map (&conf, all_paths, &mp[k], DM_DEVICE_CREATE);
 		}
 	}
 
 	/* signal multipathd that new devmaps may have come up */
-	signal_daemon();
+	signal_daemon ();
 	
 	/* free allocs */
-	free(mp);
-	free(all_paths);
-	free(all_scsi_ids);
+	free (mp);
+	free (all_paths);
+	free (all_scsi_ids);
 
 	/* release runfile */
-	unlink(RUN);
+	unlink (RUN);
 
-	exit(0);
+	exit (0);
 }
diff -urN multipath-tools-0.1.3/multipath/main.h multipath-tools-0.1.4/multipath/main.h
--- multipath-tools-0.1.3/multipath/main.h	2004-03-13 15:35:47.000000000 +0100
+++ multipath-tools-0.1.4/multipath/main.h	2004-03-16 10:25:10.000000000 +0100
@@ -103,6 +103,13 @@
 	int pindex[MAX_MP_PATHS];
 };
 
+struct hwentry {
+	char vendor[8];
+	char product[16];
+	int iopolicy;
+	int (*getuid) (char *, char *);
+};
+
 struct env {
 	int max_devs;
 	int verbose;
@@ -114,13 +121,7 @@
 	int minor;
 	char sysfs_path[FILE_NAME_SIZE];
 	char hotplugdev[FILE_NAME_SIZE];
-};
-
-struct hwentry {
-	char vendor[8];
-	char product[16];
-	int iopolicy;
-	int (*getuid) (char *, char *);
+	struct hwentry * hwtable;
 };
 
 /* Build version */
diff -urN multipath-tools-0.1.3/multipath/pgpolicies.c multipath-tools-0.1.4/multipath/pgpolicies.c
--- multipath-tools-0.1.3/multipath/pgpolicies.c	1970-01-01 01:00:00.000000000 +0100
+++ multipath-tools-0.1.4/multipath/pgpolicies.c	2004-03-16 17:53:36.000000000 +0100
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "main.h"
+#include "pgpolicies.h"
+
+#define SELECTOR	"round-robin"
+#define SELECTOR_ARGS	0
+
+extern void
+group_by_tur (struct multipath * mp, struct path * all_paths, char * str) {
+	int left_path_count = 0;
+	int right_path_count = 0;
+	int i;
+	char left_path_buff[FILE_NAME_SIZE];
+	char right_path_buff[FILE_NAME_SIZE];
+	char * left_path_buff_p = &left_path_buff[0];
+	char * right_path_buff_p = &right_path_buff[0];
+
+	for (i = 0; i <= mp->npaths; i++) {
+
+		if (all_paths[mp->pindex[i]].tur) {
+			
+			left_path_buff_p += sprintf (left_path_buff_p, " %s",
+						all_paths[mp->pindex[i]].dev);
+			
+			left_path_count++;
+
+		} else {
+
+			right_path_buff_p += sprintf (right_path_buff_p, " %s",
+						all_paths[mp->pindex[i]].dev);
+
+			right_path_count++;
+		}
+	}
+
+	if (!left_path_count)
+		sprintf (str, " 1 " SELECTOR " %i %i%s",
+			 right_path_count, SELECTOR_ARGS, right_path_buff);
+
+	else if (!right_path_count)
+		sprintf (str, " 1 " SELECTOR " %i %i%s",
+			 left_path_count, SELECTOR_ARGS, left_path_buff);
+
+	else
+		sprintf (str, " 2 " SELECTOR " %i %i%s " \
+				    SELECTOR " %i %i%s",
+			left_path_count, SELECTOR_ARGS, left_path_buff,
+			right_path_count, SELECTOR_ARGS, right_path_buff);
+}
+
+extern void
+group_by_serial (struct multipath * mp, struct path * all_paths, char * str) {
+	int path_count, pg_count = 0;
+	int i, k;
+	int * bitmap;
+	char path_buff[FILE_NAME_SIZE];
+	char pg_buff[FILE_NAME_SIZE];
+	char * path_buff_p = &path_buff[0];
+	char * pg_buff_p = &pg_buff[0];
+
+	/* init the bitmap */
+	bitmap = malloc ((mp->npaths + 1) * sizeof (int));
+	memset (bitmap, 0, (mp->npaths + 1) * sizeof (int));
+
+	for (i = 0; i <= mp->npaths; i++) {
+		if (bitmap[i])
+			continue;
+
+		/* here, we really got a new pg */
+		pg_count++;
+		path_count = 1;
+		memset (&path_buff, 0, FILE_NAME_SIZE * sizeof (char));
+		path_buff_p = &path_buff[0];
+
+		path_buff_p += sprintf (path_buff_p, " %s",
+					all_paths[mp->pindex[i]].dev);
+
+		bitmap[i] = 1;
+
+		for (k = i + 1; k <= mp->npaths; k++) {
+			
+			if (bitmap[k])
+				continue;
+
+			if (0 == strcmp (all_paths[mp->pindex[i]].serial,
+					 all_paths[mp->pindex[k]].serial)) {
+				
+				path_buff_p += sprintf (path_buff_p, " %s",
+						all_paths[mp->pindex[k]].dev);
+
+				bitmap[k] = 1;
+				path_count++;
+			}
+		}
+
+		pg_buff_p += sprintf (pg_buff_p,
+				      " " SELECTOR " %i %i%s",
+				      path_count, SELECTOR_ARGS, path_buff);
+
+	}
+
+	sprintf (str, " %i%s", pg_count, pg_buff);
+	free (bitmap);
+}
+
+
+extern void
+one_path_per_group (struct multipath * mp, struct path * all_paths, char * str)
+{
+	int i;
+	char * p;
+
+	p = str;
+
+	p += sprintf (p, " %i", mp->npaths + 1);
+
+	for (i=0; i <= mp->npaths; i++) {
+
+		if (0 != all_paths[mp->pindex[i]].sg_id.scsi_type)
+			continue;
+
+		p += sprintf (p, " " SELECTOR);
+
+		p += sprintf (p, " 1 %i", SELECTOR_ARGS);
+
+		p += sprintf (p, " %s",
+			      all_paths[mp->pindex[i]].dev);
+	}
+
+}
+
+extern void
+one_group (struct multipath * mp, struct path * all_paths, char * str)
+{
+	int i, np = 0;
+	char * p;
+
+	p = str;
+
+	for (i=0; i <= mp->npaths; i++) {
+		if (0 == all_paths[mp->pindex[i]].sg_id.scsi_type)
+		np++;
+	}
+	
+	p += sprintf (p, " 1 " SELECTOR " %i %i", np, SELECTOR_ARGS);
+	
+	for (i=0; i<= mp->npaths; i++) {
+
+		if (0 != all_paths[mp->pindex[i]].sg_id.scsi_type)
+			continue;
+
+		p += sprintf (p, " %s",
+			      all_paths[mp->pindex[i]].dev);
+	}
+}
+
diff -urN multipath-tools-0.1.3/multipath/pgpolicies.h multipath-tools-0.1.4/multipath/pgpolicies.h
--- multipath-tools-0.1.3/multipath/pgpolicies.h	1970-01-01 01:00:00.000000000 +0100
+++ multipath-tools-0.1.4/multipath/pgpolicies.h	2004-03-16 12:37:25.000000000 +0100
@@ -0,0 +1,4 @@
+void one_path_per_group (struct multipath *, struct path *, char *);
+void one_group (struct multipath *, struct path *, char *);
+void group_by_serial (struct multipath *, struct path *, char *);
+void group_by_tur (struct multipath *, struct path *, char *);
