Since msgmni now scales to the memory size, it may reach big values. To avoid forking 2*msgmni processes and create msgmni msg queues, take the min between the procfs value and MSGMNI (as found in linux/msg.h).
Also integrated the following in libipc.a:
  . get_max_msgqueues()
  . get_used_msgqueues()
Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net>
diff --git a/testcases/kernel/syscalls/ipc/lib/ipcmsg.h b/testcases/kernel/syscalls/ipc/lib/ipcmsg.h
index f745b62..e8e28ef 100644
--- a/testcases/kernel/syscalls/ipc/lib/ipcmsg.h
+++ b/testcases/kernel/syscalls/ipc/lib/ipcmsg.h
@@ -41,7 +41,9 @@
 #define MSGSIZE	1024		/* a resonable size for a message */
 #define MSGTYPE 1		/* a type ID for a message */
 
-#define MAX_MSGQUEUES	16	/* MSGMNI as defined in linux/msg.h */
+#define NR_MSGQUEUES	16	/* MSGMNI as defined in linux/msg.h */
+
+#define min(a, b)	(((a) < (b)) ? (a) : (b))
 
 typedef struct mbuf {		/* a generic message structure */
 	long mtype;
@@ -61,4 +63,7 @@
 int getipckey();
 int getuserid(char *);
 
+int get_max_msgqueues(void);
+int get_used_msgqueues(void);
+
 #endif /* ipcmsg.h */
diff --git a/testcases/kernel/syscalls/ipc/lib/libipc.c b/testcases/kernel/syscalls/ipc/lib/libipc.c
index bbfaa71..7455a5d 100644
--- a/testcases/kernel/syscalls/ipc/lib/libipc.c
+++ b/testcases/kernel/syscalls/ipc/lib/libipc.c
@@ -201,3 +201,57 @@
 		tst_resm(TINFO, "id = %d", shm_id);
 	}
 }
+
+#define BUFSIZE 512
+
+/*
+ * Get the number of message queues already in use
+ */
+int
+get_used_msgqueues()
+{
+	FILE *f;
+	int used_queues;
+	char buff[BUFSIZE];
+
+	f = popen("ipcs -q", "r");
+	if (!f) {
+		tst_resm(TBROK, "Could not run 'ipcs' to calculate used "
+			"message queues");
+		tst_exit();
+	}
+	/* FIXME: Start at -4 because ipcs prints four lines of header */
+	for (used_queues = -4; fgets(buff, BUFSIZE, f); used_queues++)
+		;
+	pclose(f);
+	if (used_queues < 0) {
+		tst_resm(TBROK, "Could not read output of 'ipcs' to "
+			"calculate used message queues");
+		tst_exit();
+	}
+	return used_queues;
+}
+
+/*
+ * Get the max number of message queues allowed on system
+ */
+int
+get_max_msgqueues()
+{
+	FILE *f;
+	char buff[BUFSIZE];
+
+	/* Get the max number of message queues allowed on system */
+	f = fopen("/proc/sys/kernel/msgmni", "r");
+	if (!f) {
+		tst_resm(TBROK, "Could not open /proc/sys/kernel/msgmni");
+		return -1;
+	}
+	if (!fgets(buff, BUFSIZE, f)) {
+		fclose(f);
+		tst_resm(TBROK, "Could not read /proc/sys/kernel/msgmni");
+		return -1;
+	}
+	fclose(f);
+	return atoi(buff);
+}
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl08.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl08.c
index ce62d49..397df3a 100644
--- a/testcases/kernel/syscalls/ipc/msgctl/msgctl08.c
+++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl08.c
@@ -455,37 +455,14 @@
 {
 }
 
-#define BUFSIZE 512
-
-/** Get the number of message queues already in use */
-static int get_used_msgqueues()
-{
-        FILE *f;
-        int used_queues;
-        char buff[BUFSIZE];
-
-        f = popen("ipcs -q", "r");
-        if (!f) {
-                tst_resm(TBROK,"Could not run 'ipcs' to calculate used message queues");
-                tst_exit();
-        }
-        /* FIXME: Start at -4 because ipcs prints four lines of header */
-        for (used_queues = -4; fgets(buff, BUFSIZE, f); used_queues++)
-                ;
-        pclose(f);
-        if (used_queues < 0) {
-                tst_resm(TBROK,"Could not read output of 'ipcs' to calculate used message queues");
-                tst_exit();
-        }
-        return used_queues;
-}
-
 /***************************************************************
  * setup() - performs all ONE TIME setup for this test.
  *****************************************************************/
 void
 setup()
 {
+	int nr_msgqs;
+
 	tst_tmpdir();
  
         /* You will want to enable some signal handling so you can capture
@@ -501,11 +478,22 @@
 	 */
         TEST_PAUSE;
 
-        MSGMNI = MAX_MSGQUEUES - get_used_msgqueues();
-	if (MSGMNI <= 0){
+	nr_msgqs = get_max_msgqueues();
+	if (nr_msgqs < 0)
+		cleanup();
+
+	nr_msgqs -= get_used_msgqueues();
+	if (nr_msgqs <= 0){
 		tst_resm(TBROK,"Max number of message queues already used, cannot create more.");
 		cleanup(); 
 	}	
+
+	/*
+	 * Since msgmni scales to the memory size, it may reach huge values
+	 * that are not necessary for this test.
+	 * That's why we define NR_MSGQUEUES as a high boundary for it.
+	 */
+	MSGMNI = min(nr_msgqs, NR_MSGQUEUES);
 }
 
 
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl09.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl09.c
index 017b917..7f8df16 100644
--- a/testcases/kernel/syscalls/ipc/msgctl/msgctl09.c
+++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl09.c
@@ -625,37 +625,14 @@
 	}
 }
 
-#define BUFSIZE 512
-
-/** Get the number of message queues already in use */
-static int get_used_msgqueues()
-{
-        FILE *f;
-        int used_queues;
-        char buff[BUFSIZE];
-
-        f = popen("ipcs -q", "r");
-        if (!f) {
-                tst_resm(TBROK,"Could not run 'ipcs' to calculate used message queues");
-                tst_exit();
-        }
-        /* FIXME: Start at -4 because ipcs prints four lines of header */
-        for (used_queues = -4; fgets(buff, BUFSIZE, f); used_queues++)
-                ;
-        pclose(f);
-        if (used_queues < 0) {
-                tst_resm(TBROK,"Could not read output of 'ipcs' to calculate used message queues");
-                tst_exit();
-        }
-        return used_queues;
-}
-
 /***************************************************************
  * setup() - performs all ONE TIME setup for this test.
  *****************************************************************/
 void
 setup()
 {
+	int nr_msgqs;
+
 	tst_tmpdir();
         /* You will want to enable some signal handling so you can capture
          * unexpected signals like SIGSEGV.
@@ -670,11 +647,22 @@
          */
         TEST_PAUSE;
 
-        MSGMNI = MAX_MSGQUEUES - get_used_msgqueues();
-        if (MSGMNI <= 0){
+        nr_msgqs = get_max_msgqueues();
+	if (nr_msgqs < 0)
+		cleanup();
+
+	nr_msgqs -= get_used_msgqueues();
+	if (nr_msgqs <= 0) {
                 tst_resm(TBROK,"Max number of message queues already used, cannot create more.");
                 cleanup();
         }
+
+	/*
+	 * Since msgmni scales to the memory size, it may reach huge values
+	 * that are not necessary for this test.
+	 * That's why we define NR_MSGQUEUES as a high boundary for it.
+	 */
+	MSGMNI = min(nr_msgqs, NR_MSGQUEUES);
 }
 
 
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl10.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl10.c
new file mode 100644
index 0000000..476d142
--- /dev/null
+++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl10.c
@@ -0,0 +1,527 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
+/* 11/06/2002   Port to LTP     dbarrera@us.ibm.com */
+
+/*
+ * NAME
+ *	msgctl10
+ *
+ * CALLS
+ *	msgget(2) msgctl(2)
+ *
+ * ALGORITHM
+ *	Get and manipulate a message queue.
+ *	Same as msgctl08 but gets the actual msgmni value under procfs.
+ *
+ * RESTRICTIONS
+ *
+ */
+
+#define _XOPEN_SOURCE 500
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <values.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include "test.h"
+#include "usctest.h"
+#include "ipcmsg.h"
+
+void setup();
+void cleanup();
+/*
+ *  *  *  * These globals must be defined in the test.
+ *   *   *   */
+
+
+char *TCID="msgctl10";           /* Test program identifier.    */
+int TST_TOTAL=1;                /* Total number of test cases. */
+extern int Tst_count;           /* Test Case counter for tst_* routines */
+
+int exp_enos[]={0};     /* List must end with 0 */
+
+#ifndef CONFIG_COLDFIRE
+#define MAXNPROCS	1000000  /* This value is set to an arbitrary high limit. */
+#else
+#define MAXNPROCS	 100000   /* Coldfire can't deal with 1000000 */
+#endif
+#define MAXNREPS	100000
+#define FAIL		1
+#define PASS		0
+
+key_t	keyarray[MAXNPROCS];
+
+struct {
+	long	type;
+	struct {
+		char	len;
+		char	pbytes[99];
+		} data;
+	} buffer;
+
+int	pidarray[MAXNPROCS];
+int tid;
+int MSGMNI,nprocs, nreps;
+int procstat;
+int dotest(key_t key, int child_process);
+int doreader(int id, long key, int child);
+int dowriter(int id,long key, int child);
+int fill_buffer(register char *buf, char val, register int size);
+int verify(register char *buf,char val, register int size,int child);
+void sig_handler();             /* signal catching function */
+int mykid;
+#ifdef UCLINUX
+static char *argv0;
+
+void do_child_1_uclinux();
+static key_t key_uclinux;
+static int i_uclinux;
+
+void do_child_2_uclinux();
+static int id_uclinux;
+static int child_process_uclinux;
+#endif
+
+/*-----------------------------------------------------------------*/
+int main(argc, argv)
+int	argc;
+char	*argv[];
+{
+	register int i, j, ok, pid;
+	int count, status;
+	struct sigaction act;
+
+#ifdef UCLINUX
+	char *msg;			/* message returned from parse_opts */
+
+	argv0 = argv[0];
+
+	/* parse standard options */
+	if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) != (char *)NULL)
+	{
+		tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
+	}
+
+	maybe_run_child(&do_child_1_uclinux, "ndd", 1, &key_uclinux, &i_uclinux);
+	maybe_run_child(&do_child_2_uclinux, "nddd", 2, &id_uclinux, &key_uclinux,
+			&child_process_uclinux);
+#endif
+
+	setup();
+
+	if (argc == 1 )
+	{
+		/* Set default parameters */
+		nreps = MAXNREPS;
+		nprocs = MSGMNI;
+	}
+	else if (argc == 3 )
+	{
+		if ( atoi(argv[1]) > MAXNREPS )
+		{
+			tst_resm(TCONF,"Requested number of iterations too large, setting to Max. of %d", MAXNREPS);
+			nreps = MAXNREPS;
+		}
+		else
+		{
+			nreps = atoi(argv[1]);
+		}
+		if (atoi(argv[2]) > MSGMNI )
+		{
+			tst_resm(TCONF,"Requested number of processes too large, setting to Max. of %d", MSGMNI);
+			nprocs = MSGMNI;
+		}
+		else
+		{
+			nprocs = atoi(argv[2]);
+		}
+	}
+	else
+	{
+		tst_resm(TCONF," Usage: %s [ number of iterations  number of processes ]", argv[0]);
+		tst_exit();
+	}
+
+	srand(getpid());
+	tid = -1;
+
+	/* Setup signal handleing routine */
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = sig_handler;
+	sigemptyset(&act.sa_mask);
+	sigaddset(&act.sa_mask, SIGTERM);
+	if (sigaction(SIGTERM, &act, NULL) < 0)
+	{
+		tst_resm(TFAIL, "Sigset SIGTERM failed");
+		tst_exit();
+	}
+	/* Set up array of unique keys for use in allocating message
+	 * queues
+	 */
+	for (i = 0; i < nprocs; i++)
+	{
+		ok = 1;
+		do
+		{
+			/* Get random key */
+			keyarray[i] = (key_t)rand();
+			/* Make sure key is unique and not private */
+			if (keyarray[i] == IPC_PRIVATE)
+			{
+				ok = 0;
+				continue;
+			}
+			for (j = 0; j < i; j++)
+			{
+				if (keyarray[j] == keyarray[i])
+				{
+					ok = 0;
+					break;
+				}
+				ok = 1;
+			}
+		} while (ok == 0);
+	}
+
+	/* Fork a number of processes, each of which will
+	 * create a message queue with one reader/writer
+	 * pair which will read and write a number (iterations)
+	 * of random length messages with specific values.
+	 */
+
+	for (i = 0; i <  nprocs; i++)
+	{
+		fflush(stdout);
+		if ((pid = FORK_OR_VFORK()) < 0)
+		{
+			tst_resm(TFAIL, "\tFork failed (may be OK if under stress)");
+			tst_exit();
+		}
+		/* Child does this */
+		if (pid == 0)
+		{
+#ifdef UCLINUX
+			if (self_exec(argv[0], "ndd", 1, keyarray[i], i) < 0)
+			{
+				tst_resm(TFAIL, "\tself_exec failed");
+				tst_exit();
+			}
+#else
+			procstat = 1;
+			exit( dotest(keyarray[i], i) );
+#endif
+		}
+		pidarray[i] = pid;
+	}
+
+	count = 0;
+	while(1)
+	{
+		if (( wait(&status)) > 0)
+		{
+			if (status>>8 != 0 )
+			{
+				tst_resm(TFAIL, "Child exit status = %d", status>>8);
+				tst_exit();
+			}
+			count++;
+		}
+		else
+		{
+			if (errno != EINTR)
+			{
+				break;
+			}
+#ifdef DEBUG
+			tst_resm(TINFO,"Signal detected during wait");
+#endif
+		}
+	}
+	/* Make sure proper number of children exited */
+	if (count != nprocs)
+	{
+		tst_resm(TFAIL, "Wrong number of children exited, Saw %d, Expected %d", count, nprocs);
+		tst_exit();
+	}
+
+	tst_resm(TPASS,"msgctl10 ran successfully!");
+
+	cleanup();
+	return (0);
+
+}
+/*--------------------------------------------------------------------*/
+
+#ifdef UCLINUX
+void
+do_child_1_uclinux()
+{
+	procstat = 1;
+	exit(dotest(key_uclinux, i_uclinux));
+}
+
+void
+do_child_2_uclinux()
+{
+	exit(doreader(id_uclinux, key_uclinux % 255, child_process_uclinux));
+}
+#endif
+
+int dotest(key, child_process)
+key_t 	key;
+int	child_process;
+{
+	int id, pid;
+
+	sighold(SIGTERM);
+	TEST(msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR));
+	if (TEST_RETURN < 0)
+	{
+		tst_resm(TFAIL, "Msgget error in child %d, errno = %d", child_process, TEST_ERRNO);
+		tst_exit();
+	}
+	tid = id = TEST_RETURN;
+	sigrelse(SIGTERM);
+
+	fflush(stdout);
+	if ((pid = FORK_OR_VFORK()) < 0)
+	{
+		tst_resm(TWARN, "\tFork failed (may be OK if under stress)");
+		TEST(msgctl(tid, IPC_RMID, 0));
+		if (TEST_RETURN < 0)
+		{
+			tst_resm(TFAIL, "Msgctl error in cleanup, errno = %d", errno);
+		}
+		tst_exit();
+	}
+	/* Child does this */
+	if (pid == 0)
+	{
+#ifdef UCLINUX
+		if (self_exec(argv0, "nddd", 2, id, key, child_process) < 0) {
+			tst_resm(TWARN, "self_exec failed");
+			TEST(msgctl(tid, IPC_RMID, 0));
+			if (TEST_RETURN < 0)
+			{
+				tst_resm(TFAIL, "\tMsgctl error in cleanup, "
+					"errno = %d\n", errno);
+			}
+			tst_exit();
+		}
+#else
+		exit( doreader(id, key % 255, child_process) );
+#endif
+	}
+	/* Parent does this */
+	mykid = pid;
+	procstat = 2;
+	dowriter(id, key % 255, child_process);
+	wait(0);
+	TEST(msgctl(id, IPC_RMID, 0));
+	if (TEST_RETURN < 0)
+	{
+		tst_resm(TFAIL, "msgctl errno %d", TEST_ERRNO);
+		tst_exit();
+	}
+	exit(PASS);
+}
+
+int doreader(id, key, child)
+int id, child;
+long key;
+{
+	int i, size;
+
+	for (i = 0; i < nreps; i++)
+	{
+		if ((size = msgrcv(id, &buffer, 100, 0, 0)) < 0)
+		{
+			tst_brkm(TBROK, cleanup, "Msgrcv error in child %d, read # = %d, errno = %d", (i + 1), child, errno);
+			tst_exit();
+		}
+		if (buffer.data.len + 1 != size)
+		{
+			tst_resm(TFAIL, "Size mismatch in child %d, read # = %d", child, (i + 1));
+			tst_resm(TFAIL, "for message size got  %d expected  %d %s",size ,buffer.data.len);
+			tst_exit();
+		}
+		if ( verify(buffer.data.pbytes, key, size - 1, child) )
+		{
+			tst_resm(TFAIL, "in read # = %d,key =  %x", (i + 1), child, key);
+			tst_exit();
+		}
+		key++;
+	}
+	return (0);
+}
+
+int dowriter(id, key, child)
+int id,child;
+long key;
+{
+	int i, size;
+
+	for (i = 0; i < nreps; i++)
+	{
+		do
+		{
+			size = (rand() % 99);
+		} while (size == 0);
+		fill_buffer(buffer.data.pbytes, key, size);
+		buffer.data.len = size;
+		buffer.type = 1;
+		TEST(msgsnd(id, &buffer, size + 1, 0));
+		if (TEST_RETURN < 0)
+		{
+			tst_brkm(TBROK, cleanup, "Msgsnd error in child %d, key =   %x errno  = %d", child, key, TEST_ERRNO);
+		}
+		key++;
+	}
+	return (0);
+}
+
+int fill_buffer(buf, val, size)
+register char *buf;
+char	val;
+register int size;
+{
+	register int i;
+
+	for(i = 0; i < size; i++)
+	{
+		buf[i] = val;
+	}
+
+	return (0);
+}
+
+
+/*
+ * verify()
+ *	Check a buffer for correct values.
+ */
+
+int verify(buf, val, size, child)
+	register char *buf;
+	char	val;
+	register int size;
+	int	child;
+{
+	while(size-- > 0)
+	{
+		if (*buf++ != val)
+		{
+			tst_resm(TWARN, "Verify error in child %d, *buf = %x, val = %x, size = %d", child, *buf, val, size);
+			return(FAIL);
+		}
+	}
+	return(PASS);
+}
+
+/*
+ *  * void
+ *  * sig_handler() - signal catching function for 'SIGUSR1' signal.
+ *  *
+ *  *   This is a null function and used only to catch the above signal
+ *  *   generated in parent process.
+ *  */
+void
+sig_handler()
+{
+}
+
+/***************************************************************
+ * setup() - performs all ONE TIME setup for this test.
+ *****************************************************************/
+void
+setup()
+{
+	int nr_msgqs;
+
+	tst_tmpdir();
+
+	/* You will want to enable some signal handling so you can capture
+	 * unexpected signals like SIGSEGV.
+	 */
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+
+	/* Pause if that option was specified */
+	/* One cavet that hasn't been fixed yet.  TEST_PAUSE contains the code to
+	 * fork the test with the -c option.  You want to make sure you do this
+	 * before you create your temporary directory.
+	 */
+	TEST_PAUSE;
+
+	nr_msgqs = get_max_msgqueues();
+	if (nr_msgqs < 0)
+		cleanup();
+
+	MSGMNI = nr_msgqs - get_used_msgqueues();
+	if (MSGMNI <= 0){
+		tst_resm(TBROK,"Max number of message queues already used, cannot create more.");
+		cleanup();
+	}
+}
+
+
+/***************************************************************
+ * cleanup() - performs all ONE TIME cleanup for this test at
+ *             completion or premature exit.
+ ****************************************************************/
+void
+cleanup()
+{
+	int status;
+	/*
+	 *  Remove the message queue from the system
+	 */
+#ifdef DEBUG
+	tst_resm(TINFO,"Removing the message queue");
+#endif
+	fflush (stdout);
+	(void) msgctl(tid, IPC_RMID, (struct msqid_ds *)NULL);
+	if ((status = msgctl(tid, IPC_STAT, (struct msqid_ds *)NULL)) != -1)
+	{
+		(void) msgctl(tid, IPC_RMID, (struct msqid_ds *)NULL);
+		tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
+		tst_exit();
+	}
+
+	fflush (stdout);
+	/*
+	 * print timing stats if that option was specified.
+	 * print errno log if that option was specified.
+	 */
+	TEST_CLEANUP;
+	tst_rmdir();
+	/* exit with return code appropriate for results */
+	tst_exit();
+}
+
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl11.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl11.c
new file mode 100644
index 0000000..c5975a0
--- /dev/null
+++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl11.c
@@ -0,0 +1,696 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
+/* 11/11/2002   Port to LTP     dbarrera@us.ibm.com */
+
+
+/*
+ * NAME
+ *	msgctl11
+ *
+ * CALLS
+ *	msgget(2) msgctl(2) msgop(2)
+ *
+ * ALGORITHM
+ *	Get and manipulate a message queue.
+ *	Same as msgctl09 but gets the actual msgmni value under procfs.
+ *
+ * RESTRICTIONS
+ *
+ */
+
+#define _XOPEN_SOURCE 500
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "test.h"
+#include "usctest.h"
+#include "ipcmsg.h"
+
+#define MAXNREPS	1000
+#ifndef CONFIG_COLDFIRE
+#define MAXNPROCS	 1000000  /* This value is set to an arbitrary high limit. */
+#else
+#define MAXNPROCS	 100000   /* Coldfire can't deal with 1000000 */
+#endif
+#define MAXNKIDS	10
+#define FAIL		1
+#define PASS		0
+
+int dotest(key_t,int);
+int doreader(long,int,int);
+int dowriter(long,int,int);
+int fill_buffer(char*,char,int);
+int verify(char*,char,int,int);
+void setup();
+void cleanup();
+
+/*
+ * These globals must be defined in the test.
+ * */
+
+
+char *TCID="msgctl11";           /* Test program identifier.    */
+int TST_TOTAL=1;                /* Total number of test cases. */
+extern int Tst_count;           /* Test Case counter for tst_* routines */
+
+int exp_enos[]={0};     /* List must end with 0 */
+
+
+key_t	keyarray[MAXNPROCS];
+
+struct {
+	long	type;
+	struct {
+		char	len;
+		char	pbytes[99];
+		} data;
+	} buffer;
+
+int	pidarray[MAXNPROCS];
+int	rkidarray[MAXNKIDS];
+int	wkidarray[MAXNKIDS];
+int 	tid;
+int 	nprocs, nreps, nkids, MSGMNI;
+int 	procstat;
+void 	term(int);
+#ifdef UCLINUX
+static char *argv0;
+
+void do_child_1_uclinux();
+static key_t key_uclinux;
+static int i_uclinux;
+
+void do_child_2_uclinux();
+static int pid_uclinux;
+static int child_process_uclinux;
+
+void do_child_3_uclinux();
+static int rkid_uclinux;
+#endif
+void cleanup_msgqueue(int i, int tid);
+
+/*-----------------------------------------------------------------*/
+int main(argc, argv)
+int	argc;
+char	*argv[];
+{
+	register int i, j, ok, pid;
+	int count, status;
+
+#ifdef UCLINUX
+	char *msg;			/* message returned from parse_opts */
+
+	argv0 = argv[0];
+
+	/* parse standard options */
+	if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) != (char *)NULL)
+	{
+		tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
+	}
+
+	maybe_run_child(&do_child_1_uclinux, "ndd", 1, &key_uclinux, &i_uclinux);
+	maybe_run_child(&do_child_2_uclinux, "nddd", 2, &key_uclinux,
+			&pid_uclinux, &child_process_uclinux);
+	maybe_run_child(&do_child_3_uclinux, "nddd", 3, &key_uclinux,
+			&rkid_uclinux, &child_process_uclinux);
+#endif
+
+	setup();
+
+	if (argc == 1 )
+	{
+		/* Set default parameters */
+		nreps = MAXNREPS;
+		nprocs = MSGMNI;
+		nkids = MAXNKIDS;
+	}
+	else if (argc == 4 )
+	{
+		if ( atoi(argv[1]) > MAXNREPS )
+		{
+			tst_resm(TCONF,"Requested number of iterations too large, setting to Max. of %d", MAXNREPS);
+			nreps = MAXNREPS;
+		}
+		else
+		{
+			nreps = atoi(argv[1]);
+		}
+		if (atoi(argv[2]) > MSGMNI )
+		{
+			tst_resm(TCONF,"Requested number of processes too large, setting to Max. of %d", MSGMNI);
+			nprocs = MSGMNI;
+		}
+		else
+		{
+			nprocs = atoi(argv[2]);
+		}
+		if (atoi(argv[3]) > MAXNKIDS )
+		{
+			tst_resm(TCONF,"Requested number of read/write pairs too large; setting to Max. of %d", MAXNKIDS);
+			nkids = MAXNKIDS;
+		}
+		else
+		{
+			nkids = atoi(argv[3]);
+		}
+	}
+	else
+	{
+		tst_resm(TCONF," Usage: %s [ number of iterations  number of processes number of read/write pairs ]", argv[0]);
+		tst_exit();
+	}
+
+	procstat = 0;
+	srand48((unsigned)getpid() + (unsigned)(getppid() << 16));
+	tid = -1;
+
+	/* Setup signal handleing routine */
+	if (sigset(SIGTERM, term) == SIG_ERR)
+	{
+		tst_resm(TFAIL, "Sigset SIGTERM failed");
+		tst_exit();
+	}
+	/* Set up array of unique keys for use in allocating message
+	 * queues
+	 */
+	for (i = 0; i < nprocs; i++)
+	{
+		ok = 1;
+		do
+		{
+			/* Get random key */
+			keyarray[i] = (key_t)lrand48();
+			/* Make sure key is unique and not private */
+			if (keyarray[i] == IPC_PRIVATE)
+			{
+				ok = 0;
+				continue;
+			}
+			for (j = 0; j < i; j++)
+			{
+				if (keyarray[j] == keyarray[i])
+				{
+					ok = 0;
+					break;
+				}
+				ok = 1;
+			}
+		} while (ok == 0);
+	}
+/*-----------------------------------------------------------------*/
+	/* Fork a number of processes (nprocs), each of which will
+	 * create a message queue with several (nkids) reader/writer
+	 * pairs which will read and write a number (iterations)
+	 * of random length messages with specific values (keys).
+	 */
+
+	for (i = 0; i <  nprocs; i++)
+	{
+		fflush(stdout);
+		if ((pid = FORK_OR_VFORK()) < 0)
+		{
+			tst_resm(TFAIL, "\tFork failed (may be OK if under stress)");
+			tst_exit();
+		}
+		/* Child does this */
+		if (pid == 0)
+		{
+#ifdef UCLINUX
+			if (self_exec(argv[0], "ndd", 1, keyarray[i], i) < 0)
+			{
+				tst_resm(TFAIL, "\tself_exec failed");
+				tst_exit();
+			}
+#else
+			procstat = 1;
+			exit( dotest(keyarray[i], i) );
+#endif
+		}
+		pidarray[i] = pid;
+	}
+
+	count = 0;
+	while(1)
+	{
+		if (( wait(&status)) > 0)
+		{
+			if (status>>8 != PASS )
+			{
+				tst_resm(TFAIL, "Child exit status = %d", status>>8);
+				tst_exit();
+			}
+			count++;
+		}
+		else
+		{
+			if (errno != EINTR)
+			{
+				break;
+			}
+#ifdef DEBUG
+			tst_resm(TINFO,"Signal detected during wait");
+#endif
+		}
+	}
+	/* Make sure proper number of children exited */
+	if (count != nprocs)
+	{
+		tst_resm(TFAIL, "Wrong number of children exited, Saw %d, Expected %d", count, nprocs);
+		tst_exit();
+	}
+
+	tst_resm(TPASS,"msgctl11 ran successfully!");
+
+	cleanup();
+
+	return (0);
+
+
+
+}
+/*--------------------------------------------------------------------*/
+
+#ifdef UCLINUX
+void
+do_child_1_uclinux()
+{
+	procstat = 1;
+	exit(dotest(key_uclinux, i_uclinux));
+}
+
+void
+do_child_2_uclinux()
+{
+	procstat = 2;
+	exit(doreader(key_uclinux, pid_uclinux, child_process_uclinux));
+}
+
+void
+do_child_3_uclinux()
+{
+	procstat = 2;
+	exit(dowriter(key_uclinux, rkid_uclinux, child_process_uclinux));
+}
+#endif
+
+void
+cleanup_msgqueue(int i, int tid)
+{
+	/*
+	 * Decrease the value of i by 1 because it
+	 * is getting incremented even if the fork
+	 * is failing.
+	 */
+
+	i--;
+	/*
+	 * Kill all children & free message queue.
+	 */
+	for (; i >= 0; i--) {
+		(void)kill(rkidarray[i], SIGKILL);
+		(void)kill(wkidarray[i], SIGKILL);
+	}
+
+	if (msgctl(tid, IPC_RMID, 0) < 0) {
+		tst_resm(TFAIL, "Msgctl error in cleanup, errno = %d", errno);
+		tst_exit();
+	}
+}
+
+int dotest(key, child_process)
+key_t 	key;
+int	child_process;
+{
+	int id, pid;
+	int i, count, status, exit_status;
+
+	sighold(SIGTERM);
+	if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR )) < 0)
+	{
+		tst_resm(TFAIL, "Msgget error in child %d, errno = %d", child_process, errno);
+		tst_exit();
+	}
+	tid = id;
+	sigrelse(SIGTERM);
+
+	exit_status = PASS;
+
+	for (i=0; i < nkids; i++)
+	{
+		fflush(stdout);
+		if ((pid = FORK_OR_VFORK()) < 0)
+		{
+			tst_resm(TWARN, "Fork failure in first child of child group %d", child_process);
+			cleanup_msgqueue(i, tid);
+			tst_exit();
+		}
+		/* First child does this */
+		if (pid == 0)
+		{
+#ifdef UCLINUX
+			if (self_exec(argv0, "nddd", 2, key, getpid(),
+							child_process) < 0) {
+				tst_resm(TWARN, "self_exec failed");
+				cleanup_msgqueue(i, tid);
+				tst_exit();
+			}
+#else
+			procstat = 2;
+			exit( doreader( key, getpid(), child_process) );
+#endif
+		}
+		rkidarray[i] = pid;
+		fflush(stdout);
+		if ((pid = FORK_OR_VFORK()) < 0)
+		{
+			tst_resm(TWARN, "Fork failure in first child of child group %d", child_process);
+			/*
+			 * Kill the reader child process
+			 */
+			(void)kill(rkidarray[i], SIGKILL);
+
+			cleanup_msgqueue(i, tid);
+			tst_exit();
+		}
+		/* Second child does this */
+		if (pid == 0)
+		{
+#ifdef UCLINUX
+			if (self_exec(argv0, "nddd", 3, key, rkidarray[i],
+							child_process) < 0) {
+				tst_resm(TWARN, "\tFork failure in first child "
+					"of child group %d \n", child_process);
+				/*
+				 * Kill the reader child process
+				 */
+				(void)kill(rkidarray[i], SIGKILL);
+
+				cleanup_msgqueue(i, tid);
+				tst_exit();
+			}
+#else
+			procstat = 2;
+			exit( dowriter( key, rkidarray[i], child_process) );
+#endif
+		}
+		wkidarray[i] = pid;
+	}
+	/* Parent does this */
+	count = 0;
+	while(1)
+	{
+		if (( wait(&status)) > 0)
+		{
+			if (status>>8 != PASS )
+			{
+				tst_resm(TFAIL, "Child exit status = %d from child group %d", status>>8, child_process);
+				for (i = 0; i < nkids; i++)
+				{
+					kill(rkidarray[i], SIGTERM);
+					kill(wkidarray[i], SIGTERM);
+				}
+				if (msgctl(tid, IPC_RMID, 0) < 0) {
+					tst_resm(TFAIL, "Msgctl error, errno = %d", errno);
+				}
+				tst_exit();
+			}
+			count++;
+		}
+		else
+		{
+			if (errno != EINTR)
+			{
+				break;
+			}
+		}
+	}
+	/* Make sure proper number of children exited */
+	if (count != (nkids * 2))
+	{
+		tst_resm(TFAIL, "Wrong number of children exited in child group %d, Saw %d Expected %d", child_process, count, (nkids * 2));
+		if (msgctl(tid, IPC_RMID, 0) < 0) {
+			tst_resm(TFAIL, "Msgctl error, errno = %d", errno);
+		}
+		tst_exit();
+	}
+	if (msgctl(id, IPC_RMID, 0) < 0)
+	{
+		tst_resm(TFAIL, "Msgctl failure in child group %d, errno %d", child_process, errno);
+		tst_exit();
+	}
+	exit(exit_status);
+}
+
+int doreader( key, type, child)
+int type, child;
+long key;
+{
+	int i, size;
+	int id;
+
+	if ((id = msgget(key, 0)) < 0)
+	{
+		tst_resm(TFAIL, "Msgget error in reader of child group %d, errno = %d", child, errno);
+		tst_exit();
+	}
+	if (id != tid)
+	{
+		tst_resm(TFAIL, "Message queue mismatch in reader of child group %d for message queue id %d", child, id);
+		tst_exit();
+	}
+	for (i = 0; i < nreps; i++)
+	{
+		if ((size = msgrcv(id, &buffer, 100, type, 0)) < 0)
+		{
+			tst_resm(TFAIL, "Msgrcv error in child %d, read # = %d, errno = %d", (i + 1), child, errno);
+			tst_exit();
+		}
+		if (buffer.type != type)
+		{
+			tst_resm(TFAIL, "Size mismatch in child %d, read # = %d", child, (i + 1));
+			tst_resm(TFAIL, "\tfor message size got  %d expected  %d %s",size ,buffer.data.len);
+			tst_exit();
+		}
+		if (buffer.data.len + 1 != size)
+		{
+			tst_resm(TFAIL, "Size mismatch in child %d, read # = %d, size = %d, expected = %d", child, (i + 1), buffer.data.len, size);
+			tst_exit();
+		}
+		if ( verify(buffer.data.pbytes, (key % 255), size - 1, child) )
+		{
+			tst_resm(TFAIL, "in read # = %d,key =  %x", (i + 1), child, key);
+			tst_exit();
+		}
+		key++;
+	}
+	exit(PASS);
+}
+
+int dowriter( key, type, child)
+int type,child;
+long key;
+{
+	int i, size;
+	int id;
+
+	if ((id = msgget(key, 0)) < 0)
+	{
+		tst_resm(TFAIL, "Msgget error in writer of child group %d, errno = %d", child, errno);
+		tst_exit();
+	}
+	if (id != tid)
+	{
+		tst_resm(TFAIL, "Message queue mismatch in writer of child group %d", child);
+		tst_resm(TFAIL, "\tfor message queue id %d expected  %d",id, tid);
+		tst_exit();
+	}
+
+	for (i = 0; i < nreps; i++)
+	{
+		do
+		{
+			size = (lrand48() % 99);
+		} while (size == 0);
+		fill_buffer(buffer.data.pbytes, (key % 255), size);
+		buffer.data.len = size;
+		buffer.type = type;
+		if (msgsnd(id, &buffer, size + 1, 0) < 0)
+		{
+			tst_resm(TFAIL, "Msgsnd error in child %d, key =   %x errno  = %d", child, key, errno);
+			tst_exit();
+		}
+		key++;
+	}
+	exit(PASS);
+}
+
+int fill_buffer(buf, val, size)
+register char *buf;
+char	val;
+register int size;
+{
+	register int i;
+
+	for(i = 0; i < size; i++)
+		buf[i] = val;
+	return(0);
+}
+
+
+/*
+ * verify()
+ *	Check a buffer for correct values.
+ */
+
+int verify(buf, val, size, child)
+	register char *buf;
+	char	val;
+	register int size;
+	int	child;
+{
+	while(size-- > 0)
+		if (*buf++ != val)
+		{
+			tst_resm(TWARN, "Verify error in child %d, *buf = %x, val = %x, size = %d", child, *buf, val, size);
+			return(FAIL);
+		}
+	return(PASS);
+}
+
+/* ARGSUSED */
+void
+term(int sig)
+{
+	int i;
+
+	if (procstat == 0)
+	{
+#ifdef DEBUG
+		tst_resm(TINFO,"SIGTERM signal received, test killing kids");
+#endif
+		for (i = 0; i < nprocs; i++)
+		{
+			if ( pidarray[i] > 0){
+				if ( kill(pidarray[i], SIGTERM) < 0)
+				{
+					tst_resm(TBROK,"Kill failed to kill child %d", i);
+					exit(FAIL);
+				}
+			}
+		}
+		return;
+	}
+
+	if (procstat == 2)
+	{
+		fflush(stdout);
+		exit(PASS);
+	}
+
+	if (tid == -1)
+	{
+		exit(FAIL);
+	}
+	for (i = 0; i < nkids; i++)
+	{
+		if (rkidarray[i] > 0)
+			kill(rkidarray[i], SIGTERM);
+		if (wkidarray[i] > 0)
+			kill(wkidarray[i], SIGTERM);
+	}
+}
+
+/***************************************************************
+ * setup() - performs all ONE TIME setup for this test.
+ *****************************************************************/
+void
+setup()
+{
+	int nr_msgqs;
+
+	tst_tmpdir();
+	/* You will want to enable some signal handling so you can capture
+	 * unexpected signals like SIGSEGV.
+	 */
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+
+	/* Pause if that option was specified */
+	/* One cavet that hasn't been fixed yet.  TEST_PAUSE contains the code to
+	 * fork the test with the -c option.  You want to make sure you do this
+	 * before you create your temporary directory.
+	 */
+	TEST_PAUSE;
+
+	nr_msgqs = get_max_msgqueues();
+	if (nr_msgqs < 0)
+		cleanup();
+
+	MSGMNI = nr_msgqs - get_used_msgqueues();
+	if (MSGMNI <= 0){
+		tst_resm(TBROK,"Max number of message queues already used, cannot create more.");
+		cleanup();
+	}
+}
+
+
+/***************************************************************
+ * cleanup() - performs all ONE TIME cleanup for this test at
+ * completion or premature exit.
+ ****************************************************************/
+void
+cleanup()
+{
+	int status;
+	/*
+	 * print timing stats if that option was specified.
+	 * print errno log if that option was specified.
+	 */
+	TEST_CLEANUP;
+
+	/*
+	 * Remove the message queue from the system
+	 */
+#ifdef DEBUG
+	tst_resm(TINFO,"Removing the message queue");
+#endif
+	fflush (stdout);
+	(void) msgctl(tid, IPC_RMID, (struct msqid_ds *)NULL);
+	if ((status = msgctl(tid, IPC_STAT, (struct msqid_ds *)NULL)) != -1) {
+		(void) msgctl(tid, IPC_RMID, (struct msqid_ds *)NULL);
+		tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
+		tst_exit();
+	}
+
+	fflush (stdout);
+	tst_rmdir();
+	/* exit with return code appropriate for results */
+	tst_exit();
+}
+
diff --git a/testcases/kernel/syscalls/ipc/msgget/Makefile b/testcases/kernel/syscalls/ipc/msgget/Makefile
index 9071354..fe06f06 100644
--- a/testcases/kernel/syscalls/ipc/msgget/Makefile
+++ b/testcases/kernel/syscalls/ipc/msgget/Makefile
@@ -21,9 +21,12 @@
 
 SRCS    = $(wildcard *.c)
 TARGETS = $(patsubst %.c,%,$(SRCS))
+LIBIPC_HEADERS	= ../lib/ipcmsg.h
 
 all: $(TARGETS)
 
+$(TARGETS):	$(LIBIPC_HEADERS)
+
 install:
 	@set -e; for i in $(TARGETS); do ln -f $$i ../../../../bin/$$i ; done
 
diff --git a/testcases/kernel/syscalls/ipc/msgget/msgget03.c b/testcases/kernel/syscalls/ipc/msgget/msgget03.c
index d7bc315..de19d09 100644
--- a/testcases/kernel/syscalls/ipc/msgget/msgget03.c
+++ b/testcases/kernel/syscalls/ipc/msgget/msgget03.c
@@ -68,8 +68,6 @@
 int *msg_q_arr = NULL;		/* hold the id's that we create */
 int num_queue = 0;		/* count the queues created */
 
-static int get_max_msgqueues();
-
 int main(int ac, char **av)
 {
 	int lc;				/* loop counter */
@@ -121,24 +119,6 @@
 	return(0);
 }
 
-/** Get the max number of message queues allowed on system */
-int get_max_msgqueues()
-{
-        FILE *f;
-        char buff[512];
-
-        /* Get the max number of message queues allowed on system */
-        f = fopen("/proc/sys/kernel/msgmni", "r");
-        if (!f){
-                tst_brkm(TBROK, cleanup, "Could not open /proc/sys/kernel/msgmni");
-        }
-        if (!fgets(buff, 512, f)) {
-                tst_brkm(TBROK, cleanup, "Could not read /proc/sys/kernel/msgmni");
-        }
-        fclose(f);
-        return atoi(buff);
-}
-
 /*
  * setup() - performs all the ONE TIME setup for this test.
  */
@@ -166,6 +146,8 @@
 	msgkey = getipckey();
 
 	maxmsgs = get_max_msgqueues();
+	if (maxmsgs < 0)
+		tst_brkm(TBROK, cleanup, "");
 
 	msg_q_arr = (int *)calloc(maxmsgs, sizeof (int));
 	if (msg_q_arr == NULL) {