tests: add IPC_STAT to ipc tests, workaround limitiations of old kernels

* tests/ipc_msg.c: Include <errno.h>.
(main): Add a test call with IPC_STAT, handle old kernels MSG_STAT behaviour.
* tests/ipc_sem.c: Include <errno.h>.
(main): Add a test call with IPC_STAT, handle old kernels SEM_STAT behaviour.
* tests/ipc_shm.c: Include <errno.h>.
(main): Add a test call with IPC_STAT, handle old kernels SHM_STAT behaviour.
diff --git a/tests/ipc_msg.c b/tests/ipc_msg.c
index 4888d3a..1917086 100644
--- a/tests/ipc_msg.c
+++ b/tests/ipc_msg.c
@@ -1,31 +1,48 @@
 #include <stdio.h>
+#include <errno.h>
 #include <sys/msg.h>
 
 int
 main(void)
 {
-	int id = msgget(IPC_PRIVATE, 0600);
+	int rc, id;
+	struct msqid_ds ds;
+
+	id = msgget(IPC_PRIVATE, 0600);
 	if (id < 0)
 		return 77;
 	printf("msgget\\(IPC_PRIVATE, 0600\\) += %d\n", id);
 
-	int rc = 1;
+	if (msgctl(id, IPC_STAT, &ds))
+		goto fail;
+	printf("msgctl\\(%d, IPC_STAT, %p\\) += 0\n", id, &ds);
 
-	struct msqid_ds ds;
 	int max = msgctl(0, MSG_INFO, &ds);
 	if (max < 0)
 		goto fail;
 	printf("msgctl\\(0, MSG_INFO, %p\\) += %d\n", &ds, max);
 
-	if (msgctl(id, MSG_STAT, &ds) != id)
-		goto fail;
-	printf("msgctl\\(%d, MSG_STAT, %p\\) += %d\n", id, &ds, id);
+	rc = msgctl(id, MSG_STAT, &ds);
+	if (rc != id) {
+		/*
+		 * In linux < v2.6.24-rc1 the first argument must be
+		 * an index in the kernel's internal array.
+		 */
+		if (-1 != rc || EINVAL != errno)
+			goto fail;
+		printf("msgctl\\(%d, MSG_STAT, %p\\) += -1 EINVAL \\(Invalid argument\\)\n", id, &ds);
+	} else {
+		printf("msgctl\\(%d, MSG_STAT, %p\\) += %d\n", id, &ds, id);
+	}
 
 	rc = 0;
-
-fail:
+done:
 	if (msgctl(id, IPC_RMID, 0) < 0)
 		return 1;
 	printf("msgctl\\(%d, IPC_RMID, 0\\) += 0\n", id);
 	return rc;
+
+fail:
+	rc = 1;
+	goto done;
 }