• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _XOPEN_SOURCE
2 #define _XOPEN_SOURCE 700
3 #endif
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <time.h>
8 #include <sys/types.h>
9 #include <sys/msg.h>
10 #include <sys/wait.h>
11 #include <unistd.h>
12 #include "test.h"
13 
14 static const char path[] = ".";
15 static const int id = 'm';
16 
17 #define T(f) do{ \
18 	if ((f)+1 == 0) \
19 		t_error("%s failed: %s\n", #f, strerror(errno)); \
20 }while(0)
21 
22 #define EQ(a,b,fmt) do{ \
23 	if ((a) != (b)) \
24 		t_error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
25 }while(0)
26 
snd()27 static void snd()
28 {
29 	time_t t;
30 	key_t k;
31 	int qid;
32 	struct msqid_ds qid_ds;
33 	struct {
34 		long type;
35 		char data[20];
36 	} msg = {1, "test message"};
37 
38 	T(t = time(0));
39 	T(k = ftok(path, id));
40 
41 	/* make sure we get a clean message queue id */
42 	T(qid = msgget(k, IPC_CREAT|0666));
43 	T(msgctl(qid, IPC_RMID, 0));
44 	T(qid = msgget(k, IPC_CREAT|IPC_EXCL|0666));
45 
46 	if (t_status)
47 		exit(t_status);
48 
49 	/* check IPC_EXCL */
50 	errno = 0;
51 	if (msgget(k, IPC_CREAT|IPC_EXCL|0666) != -1 || errno != EEXIST)
52 		t_error("msgget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
53 
54 	/* check if msgget initilaized the msqid_ds structure correctly */
55 	T(msgctl(qid, IPC_STAT, &qid_ds));
56 	EQ(qid_ds.msg_perm.cuid, geteuid(), "got %d, want %d");
57 	EQ(qid_ds.msg_perm.uid, geteuid(), "got %d, want %d");
58 	EQ(qid_ds.msg_perm.cgid, getegid(), "got %d, want %d");
59 	EQ(qid_ds.msg_perm.gid, getegid(), "got %d, want %d");
60 	EQ(qid_ds.msg_perm.mode & 0x1ff, 0666, "got %o, want %o");
61 	EQ(qid_ds.msg_qnum, 0, "got %d, want %d");
62 	EQ(qid_ds.msg_lspid, 0, "got %d, want %d");
63 	EQ(qid_ds.msg_lrpid, 0, "got %d, want %d");
64 	EQ((long long)qid_ds.msg_stime, 0, "got %lld, want %d");
65 	EQ((long long)qid_ds.msg_rtime, 0, "got %lld, want %d");
66 	if (qid_ds.msg_ctime < t)
67 		t_error("qid_ds.msg_ctime >= t failed: got %lld, want >= %lld\n", (long long)qid_ds.msg_ctime, (long long)t);
68 	if (qid_ds.msg_ctime > t+5)
69 		t_error("qid_ds.msg_ctime <= t+5 failed: got %lld, want <= %lld\n", (long long)qid_ds.msg_ctime, (long long)t+5);
70 	if (qid_ds.msg_qbytes <= 0)
71 		t_error("qid_ds.msg_qbytes > 0 failed: got %d, want > 0\n", qid_ds.msg_qbytes, t);
72 
73 	/* test send */
74 	T(msgsnd(qid, &msg, sizeof msg.data, IPC_NOWAIT));
75 	T(msgctl(qid, IPC_STAT, &qid_ds));
76 	EQ(qid_ds.msg_qnum, 1, "got %d, want %d");
77 	EQ(qid_ds.msg_lspid, getpid(), "got %d, want %d");
78 	if (qid_ds.msg_stime < t)
79 		t_error("msg_stime is %lld want >= %lld\n", (long long)qid_ds.msg_stime, (long long)t);
80 	if (qid_ds.msg_stime > t+5)
81 		t_error("msg_stime is %lld want <= %lld\n", (long long)qid_ds.msg_stime, (long long)t+5);
82 }
83 
rcv()84 static void rcv()
85 {
86 	key_t k;
87 	int qid;
88 	struct {
89 		long type;
90 		char data[20];
91 	} msg;
92 	long msgtyp = 0;
93 
94 	T(k = ftok(path, id));
95 	T(qid = msgget(k, 0));
96 
97 	errno = 0;
98 	if (msgrcv(qid, &msg, 0, msgtyp, 0) != -1 || errno != E2BIG)
99 		t_error("msgrcv should have failed when msgsize==0 with E2BIG, got %s\n", strerror(errno));
100 
101 	/* test receive */
102 	T(msgrcv(qid, &msg, sizeof msg.data, msgtyp, IPC_NOWAIT));
103 	if (strcmp(msg.data,"test message") != 0)
104 		t_error("received \"%s\" instead of \"%s\"\n", msg.data, "test message");
105 
106 	errno = 0;
107 	if (msgrcv(qid, &msg, sizeof msg.data, msgtyp, MSG_NOERROR|IPC_NOWAIT) != -1 || errno != ENOMSG)
108 		t_error("msgrcv should have failed when ther is no msg with ENOMSG, got %s\n", strerror(errno));
109 
110 	/* cleanup */
111 	T(msgctl(qid, IPC_RMID, 0));
112 }
113 
main(void)114 int main(void)
115 {
116 	int p;
117 	int status;
118 
119 	snd();
120 	p = fork();
121 	if (p == -1)
122 		t_error("fork failed: %s\n", strerror(errno));
123 	else if (p == 0)
124 		rcv();
125 	else {
126 		T(waitpid(p, &status, 0));
127 		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
128 			t_error("child exit status: %d\n", status);
129 	}
130 	return t_status;
131 }
132