1570af302Sopenharmony_ci#ifndef _XOPEN_SOURCE 2570af302Sopenharmony_ci#define _XOPEN_SOURCE 700 3570af302Sopenharmony_ci#endif 4570af302Sopenharmony_ci#include <errno.h> 5570af302Sopenharmony_ci#include <stdlib.h> 6570af302Sopenharmony_ci#include <string.h> 7570af302Sopenharmony_ci#include <time.h> 8570af302Sopenharmony_ci#include <sys/types.h> 9570af302Sopenharmony_ci#include <sys/msg.h> 10570af302Sopenharmony_ci#include <sys/wait.h> 11570af302Sopenharmony_ci#include <unistd.h> 12570af302Sopenharmony_ci#include "test.h" 13570af302Sopenharmony_ci 14570af302Sopenharmony_cistatic const char path[] = "."; 15570af302Sopenharmony_cistatic const int id = 'm'; 16570af302Sopenharmony_ci 17570af302Sopenharmony_ci#define T(f) do{ \ 18570af302Sopenharmony_ci if ((f)+1 == 0) \ 19570af302Sopenharmony_ci t_error("%s failed: %s\n", #f, strerror(errno)); \ 20570af302Sopenharmony_ci}while(0) 21570af302Sopenharmony_ci 22570af302Sopenharmony_ci#define EQ(a,b,fmt) do{ \ 23570af302Sopenharmony_ci if ((a) != (b)) \ 24570af302Sopenharmony_ci t_error("%s == %s failed: " fmt "\n", #a, #b, a, b); \ 25570af302Sopenharmony_ci}while(0) 26570af302Sopenharmony_ci 27570af302Sopenharmony_cistatic void snd() 28570af302Sopenharmony_ci{ 29570af302Sopenharmony_ci time_t t; 30570af302Sopenharmony_ci key_t k; 31570af302Sopenharmony_ci int qid; 32570af302Sopenharmony_ci struct msqid_ds qid_ds; 33570af302Sopenharmony_ci struct { 34570af302Sopenharmony_ci long type; 35570af302Sopenharmony_ci char data[20]; 36570af302Sopenharmony_ci } msg = {1, "test message"}; 37570af302Sopenharmony_ci 38570af302Sopenharmony_ci T(t = time(0)); 39570af302Sopenharmony_ci T(k = ftok(path, id)); 40570af302Sopenharmony_ci 41570af302Sopenharmony_ci /* make sure we get a clean message queue id */ 42570af302Sopenharmony_ci T(qid = msgget(k, IPC_CREAT|0666)); 43570af302Sopenharmony_ci T(msgctl(qid, IPC_RMID, 0)); 44570af302Sopenharmony_ci T(qid = msgget(k, IPC_CREAT|IPC_EXCL|0666)); 45570af302Sopenharmony_ci 46570af302Sopenharmony_ci if (t_status) 47570af302Sopenharmony_ci exit(t_status); 48570af302Sopenharmony_ci 49570af302Sopenharmony_ci /* check IPC_EXCL */ 50570af302Sopenharmony_ci errno = 0; 51570af302Sopenharmony_ci if (msgget(k, IPC_CREAT|IPC_EXCL|0666) != -1 || errno != EEXIST) 52570af302Sopenharmony_ci t_error("msgget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno)); 53570af302Sopenharmony_ci 54570af302Sopenharmony_ci /* check if msgget initilaized the msqid_ds structure correctly */ 55570af302Sopenharmony_ci T(msgctl(qid, IPC_STAT, &qid_ds)); 56570af302Sopenharmony_ci EQ(qid_ds.msg_perm.cuid, geteuid(), "got %d, want %d"); 57570af302Sopenharmony_ci EQ(qid_ds.msg_perm.uid, geteuid(), "got %d, want %d"); 58570af302Sopenharmony_ci EQ(qid_ds.msg_perm.cgid, getegid(), "got %d, want %d"); 59570af302Sopenharmony_ci EQ(qid_ds.msg_perm.gid, getegid(), "got %d, want %d"); 60570af302Sopenharmony_ci EQ(qid_ds.msg_perm.mode & 0x1ff, 0666, "got %o, want %o"); 61570af302Sopenharmony_ci EQ(qid_ds.msg_qnum, 0, "got %d, want %d"); 62570af302Sopenharmony_ci EQ(qid_ds.msg_lspid, 0, "got %d, want %d"); 63570af302Sopenharmony_ci EQ(qid_ds.msg_lrpid, 0, "got %d, want %d"); 64570af302Sopenharmony_ci EQ((long long)qid_ds.msg_stime, 0, "got %lld, want %d"); 65570af302Sopenharmony_ci EQ((long long)qid_ds.msg_rtime, 0, "got %lld, want %d"); 66570af302Sopenharmony_ci if (qid_ds.msg_ctime < t) 67570af302Sopenharmony_ci t_error("qid_ds.msg_ctime >= t failed: got %lld, want >= %lld\n", (long long)qid_ds.msg_ctime, (long long)t); 68570af302Sopenharmony_ci if (qid_ds.msg_ctime > t+5) 69570af302Sopenharmony_ci t_error("qid_ds.msg_ctime <= t+5 failed: got %lld, want <= %lld\n", (long long)qid_ds.msg_ctime, (long long)t+5); 70570af302Sopenharmony_ci if (qid_ds.msg_qbytes <= 0) 71570af302Sopenharmony_ci t_error("qid_ds.msg_qbytes > 0 failed: got %d, want > 0\n", qid_ds.msg_qbytes, t); 72570af302Sopenharmony_ci 73570af302Sopenharmony_ci /* test send */ 74570af302Sopenharmony_ci T(msgsnd(qid, &msg, sizeof msg.data, IPC_NOWAIT)); 75570af302Sopenharmony_ci T(msgctl(qid, IPC_STAT, &qid_ds)); 76570af302Sopenharmony_ci EQ(qid_ds.msg_qnum, 1, "got %d, want %d"); 77570af302Sopenharmony_ci EQ(qid_ds.msg_lspid, getpid(), "got %d, want %d"); 78570af302Sopenharmony_ci if (qid_ds.msg_stime < t) 79570af302Sopenharmony_ci t_error("msg_stime is %lld want >= %lld\n", (long long)qid_ds.msg_stime, (long long)t); 80570af302Sopenharmony_ci if (qid_ds.msg_stime > t+5) 81570af302Sopenharmony_ci t_error("msg_stime is %lld want <= %lld\n", (long long)qid_ds.msg_stime, (long long)t+5); 82570af302Sopenharmony_ci} 83570af302Sopenharmony_ci 84570af302Sopenharmony_cistatic void rcv() 85570af302Sopenharmony_ci{ 86570af302Sopenharmony_ci key_t k; 87570af302Sopenharmony_ci int qid; 88570af302Sopenharmony_ci struct { 89570af302Sopenharmony_ci long type; 90570af302Sopenharmony_ci char data[20]; 91570af302Sopenharmony_ci } msg; 92570af302Sopenharmony_ci long msgtyp = 0; 93570af302Sopenharmony_ci 94570af302Sopenharmony_ci T(k = ftok(path, id)); 95570af302Sopenharmony_ci T(qid = msgget(k, 0)); 96570af302Sopenharmony_ci 97570af302Sopenharmony_ci errno = 0; 98570af302Sopenharmony_ci if (msgrcv(qid, &msg, 0, msgtyp, 0) != -1 || errno != E2BIG) 99570af302Sopenharmony_ci t_error("msgrcv should have failed when msgsize==0 with E2BIG, got %s\n", strerror(errno)); 100570af302Sopenharmony_ci 101570af302Sopenharmony_ci /* test receive */ 102570af302Sopenharmony_ci T(msgrcv(qid, &msg, sizeof msg.data, msgtyp, IPC_NOWAIT)); 103570af302Sopenharmony_ci if (strcmp(msg.data,"test message") != 0) 104570af302Sopenharmony_ci t_error("received \"%s\" instead of \"%s\"\n", msg.data, "test message"); 105570af302Sopenharmony_ci 106570af302Sopenharmony_ci errno = 0; 107570af302Sopenharmony_ci if (msgrcv(qid, &msg, sizeof msg.data, msgtyp, MSG_NOERROR|IPC_NOWAIT) != -1 || errno != ENOMSG) 108570af302Sopenharmony_ci t_error("msgrcv should have failed when ther is no msg with ENOMSG, got %s\n", strerror(errno)); 109570af302Sopenharmony_ci 110570af302Sopenharmony_ci /* cleanup */ 111570af302Sopenharmony_ci T(msgctl(qid, IPC_RMID, 0)); 112570af302Sopenharmony_ci} 113570af302Sopenharmony_ci 114570af302Sopenharmony_ciint main(void) 115570af302Sopenharmony_ci{ 116570af302Sopenharmony_ci int p; 117570af302Sopenharmony_ci int status; 118570af302Sopenharmony_ci 119570af302Sopenharmony_ci snd(); 120570af302Sopenharmony_ci p = fork(); 121570af302Sopenharmony_ci if (p == -1) 122570af302Sopenharmony_ci t_error("fork failed: %s\n", strerror(errno)); 123570af302Sopenharmony_ci else if (p == 0) 124570af302Sopenharmony_ci rcv(); 125570af302Sopenharmony_ci else { 126570af302Sopenharmony_ci T(waitpid(p, &status, 0)); 127570af302Sopenharmony_ci if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 128570af302Sopenharmony_ci t_error("child exit status: %d\n", status); 129570af302Sopenharmony_ci } 130570af302Sopenharmony_ci return t_status; 131570af302Sopenharmony_ci} 132