xref: /freebsd-src/contrib/netbsd-tests/kernel/t_sysv.c (revision 20917cac7bcf216225a7b66f7b3a56f3764c5acc)
157718be8SEnji Cooper /*	$NetBSD: t_sysv.c,v 1.4 2014/03/02 20:13:12 jmmv Exp $	*/
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 1999, 2007 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
957718be8SEnji Cooper  * NASA Ames Research Center, and by Andrew Doran.
1057718be8SEnji Cooper  *
1157718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
1257718be8SEnji Cooper  * modification, are permitted provided that the following conditions
1357718be8SEnji Cooper  * are met:
1457718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1557718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1657718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1757718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1857718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1957718be8SEnji Cooper  *
2057718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2157718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2257718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2357718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2457718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2557718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2657718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2757718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2857718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2957718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3057718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
3157718be8SEnji Cooper  */
3257718be8SEnji Cooper 
3357718be8SEnji Cooper /*
3457718be8SEnji Cooper  * Test the SVID-compatible Message Queue facility.
3557718be8SEnji Cooper  */
3657718be8SEnji Cooper 
3757718be8SEnji Cooper #include <atf-c.h>
3857718be8SEnji Cooper 
3957718be8SEnji Cooper #include <err.h>
4057718be8SEnji Cooper #include <errno.h>
4157718be8SEnji Cooper #include <fcntl.h>
4257718be8SEnji Cooper #include <signal.h>
4357718be8SEnji Cooper #include <stdio.h>
4457718be8SEnji Cooper #include <stdlib.h>
4557718be8SEnji Cooper #include <string.h>
4657718be8SEnji Cooper #include <time.h>
4757718be8SEnji Cooper #include <unistd.h>
4857718be8SEnji Cooper 
4957718be8SEnji Cooper #include <sys/ipc.h>
50ea7e7006SKonstantin Belousov #include <sys/mman.h>
5157718be8SEnji Cooper #include <sys/msg.h>
5257718be8SEnji Cooper #include <sys/param.h>
5357718be8SEnji Cooper #include <sys/sem.h>
5457718be8SEnji Cooper #include <sys/shm.h>
5557718be8SEnji Cooper #include <sys/wait.h>
5657718be8SEnji Cooper 
57*20917cacSEric van Gyzen volatile int did_sigsys;
5857718be8SEnji Cooper 
5957718be8SEnji Cooper void	sigsys_handler(int);
6057718be8SEnji Cooper 
6157718be8SEnji Cooper key_t	get_ftok(int);
6257718be8SEnji Cooper 
6357718be8SEnji Cooper void	print_msqid_ds(struct msqid_ds *, mode_t);
6457718be8SEnji Cooper void	receiver(void);
6557718be8SEnji Cooper 
6657718be8SEnji Cooper void	print_semid_ds(struct semid_ds *, mode_t);
6757718be8SEnji Cooper void	waiter(void);
6857718be8SEnji Cooper 
6957718be8SEnji Cooper void	print_shmid_ds(struct shmid_ds *, mode_t);
7057718be8SEnji Cooper void	sharer(void);
7157718be8SEnji Cooper 
7257718be8SEnji Cooper #define	MESSAGE_TEXT_LEN	256
7357718be8SEnji Cooper 
745e1e3ea2SBrooks Davis struct testmsg {
7557718be8SEnji Cooper 	long	mtype;
7657718be8SEnji Cooper 	char	mtext[MESSAGE_TEXT_LEN];
7757718be8SEnji Cooper };
7857718be8SEnji Cooper 
7957718be8SEnji Cooper const char *m1_str = "California is overrated.";
8057718be8SEnji Cooper const char *m2_str = "The quick brown fox jumped over the lazy dog.";
8157718be8SEnji Cooper 
8257718be8SEnji Cooper size_t	pgsize;
8357718be8SEnji Cooper 
8457718be8SEnji Cooper #define	MTYPE_1		1
8557718be8SEnji Cooper #define	MTYPE_1_ACK	2
8657718be8SEnji Cooper 
8757718be8SEnji Cooper #define	MTYPE_2		3
8857718be8SEnji Cooper #define	MTYPE_2_ACK	4
8957718be8SEnji Cooper 
9057718be8SEnji Cooper pid_t	child_pid;
9157718be8SEnji Cooper 
9257718be8SEnji Cooper key_t	msgkey, semkey, shmkey;
9357718be8SEnji Cooper 
9457718be8SEnji Cooper int	maxloop = 1;
9557718be8SEnji Cooper 
9657718be8SEnji Cooper union semun {
9757718be8SEnji Cooper 	int	val;		/* value for SETVAL */
9857718be8SEnji Cooper 	struct	semid_ds *buf;	/* buffer for IPC_{STAT,SET} */
9957718be8SEnji Cooper 	u_short	*array;		/* array for GETALL & SETALL */
10057718be8SEnji Cooper };
10157718be8SEnji Cooper 
10257718be8SEnji Cooper 
10357718be8SEnji Cooper /* Writes an integer to a file.  To be used from the body of the test
10457718be8SEnji Cooper  * cases below to pass any global identifiers to the cleanup routine. */
10557718be8SEnji Cooper static void
write_int(const char * path,const int value)10657718be8SEnji Cooper write_int(const char *path, const int value)
10757718be8SEnji Cooper {
10857718be8SEnji Cooper 	int output;
10957718be8SEnji Cooper 
11057718be8SEnji Cooper 	output = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
11157718be8SEnji Cooper 	ATF_REQUIRE_MSG(output != -1, "Failed to create %s", path);
11257718be8SEnji Cooper 	write(output, &value, sizeof(value));
11357718be8SEnji Cooper 	close(output);
11457718be8SEnji Cooper }
11557718be8SEnji Cooper 
11657718be8SEnji Cooper 
11757718be8SEnji Cooper /* Reads an integer from a file.  To be used from the cleanup routines
11857718be8SEnji Cooper  * of the test cases below. */
11957718be8SEnji Cooper static int
read_int(const char * path)12057718be8SEnji Cooper read_int(const char *path)
12157718be8SEnji Cooper {
12257718be8SEnji Cooper 	int input;
12357718be8SEnji Cooper 
12457718be8SEnji Cooper 	input = open(path, O_RDONLY);
12557718be8SEnji Cooper 	if (input == -1)
12657718be8SEnji Cooper 		return -1;
12757718be8SEnji Cooper 	else {
12857718be8SEnji Cooper 		int value;
129fa82818fSAlan Somers 		ATF_REQUIRE_EQ(read(input, &value, sizeof(value)), sizeof(value));
130fa82818fSAlan Somers 		close(input);
13157718be8SEnji Cooper 		return value;
13257718be8SEnji Cooper 	}
13357718be8SEnji Cooper }
13457718be8SEnji Cooper 
13557718be8SEnji Cooper 
13657718be8SEnji Cooper void
sigsys_handler(int signo)13757718be8SEnji Cooper sigsys_handler(int signo)
13857718be8SEnji Cooper {
13957718be8SEnji Cooper 
14057718be8SEnji Cooper 	did_sigsys = 1;
14157718be8SEnji Cooper }
14257718be8SEnji Cooper 
get_ftok(int id)14357718be8SEnji Cooper key_t get_ftok(int id)
14457718be8SEnji Cooper {
14557718be8SEnji Cooper 	int fd;
14657718be8SEnji Cooper 	char token_key[64], token_dir[64];
14757718be8SEnji Cooper 	char *tmpdir;
14857718be8SEnji Cooper 	key_t key;
14957718be8SEnji Cooper 
15057718be8SEnji Cooper 	strlcpy(token_key, "/tmp/t_sysv.XXXXXX", sizeof(token_key));
15157718be8SEnji Cooper 	tmpdir = mkdtemp(token_key);
15257718be8SEnji Cooper 	ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp() failed: %d", errno);
15357718be8SEnji Cooper 
15457718be8SEnji Cooper 	strlcpy(token_dir, tmpdir, sizeof(token_dir));
15557718be8SEnji Cooper 	strlcpy(token_key, tmpdir, sizeof(token_key));
15657718be8SEnji Cooper 	strlcat(token_key, "/token_key", sizeof(token_key));
15757718be8SEnji Cooper 
15857718be8SEnji Cooper 	/* Create the file, since ftok() requires it to exist! */
15957718be8SEnji Cooper 
1605e1e3ea2SBrooks Davis 	fd = open(token_key, O_RDWR | O_CREAT | O_EXCL, 0600);
16157718be8SEnji Cooper 	if (fd == -1) {
16257718be8SEnji Cooper 		rmdir(tmpdir);
16357718be8SEnji Cooper 		atf_tc_fail("open() of temp file failed: %d", errno);
16457718be8SEnji Cooper 		return (key_t)-1;
16557718be8SEnji Cooper 	} else
16657718be8SEnji Cooper 		close(fd);
16757718be8SEnji Cooper 
16857718be8SEnji Cooper 	key = ftok(token_key, id);
16957718be8SEnji Cooper 
17057718be8SEnji Cooper 	ATF_REQUIRE_MSG(unlink(token_key) != -1, "unlink() failed: %d", errno);
17157718be8SEnji Cooper 	ATF_REQUIRE_MSG(rmdir(token_dir) != -1, "rmdir() failed: %d", errno);
17257718be8SEnji Cooper 
17357718be8SEnji Cooper 	return key;
17457718be8SEnji Cooper }
17557718be8SEnji Cooper 
17657718be8SEnji Cooper ATF_TC_WITH_CLEANUP(msg);
ATF_TC_HEAD(msg,tc)17757718be8SEnji Cooper ATF_TC_HEAD(msg, tc)
17857718be8SEnji Cooper {
17957718be8SEnji Cooper 
18057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "3");
18157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing");
18257718be8SEnji Cooper }
18357718be8SEnji Cooper 
ATF_TC_BODY(msg,tc)18457718be8SEnji Cooper ATF_TC_BODY(msg, tc)
18557718be8SEnji Cooper {
18657718be8SEnji Cooper 	struct sigaction sa;
18757718be8SEnji Cooper 	struct msqid_ds m_ds;
1885e1e3ea2SBrooks Davis 	struct testmsg m;
18957718be8SEnji Cooper 	int sender_msqid;
19057718be8SEnji Cooper 	int loop;
19157718be8SEnji Cooper 	int c_status;
192*20917cacSEric van Gyzen 	pid_t wait_result;
193f4beb2edSLi-Wen Hsu 
19457718be8SEnji Cooper 	/*
19557718be8SEnji Cooper 	 * Install a SIGSYS handler so that we can exit gracefully if
19657718be8SEnji Cooper 	 * System V Message Queue support isn't in the kernel.
19757718be8SEnji Cooper 	 */
19857718be8SEnji Cooper 	did_sigsys = 0;
19957718be8SEnji Cooper 	sa.sa_handler = sigsys_handler;
20057718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
20157718be8SEnji Cooper 	sa.sa_flags = 0;
20257718be8SEnji Cooper 	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
20357718be8SEnji Cooper 	    "sigaction SIGSYS: %d", errno);
20457718be8SEnji Cooper 
20557718be8SEnji Cooper 	msgkey = get_ftok(4160);
20657718be8SEnji Cooper 	ATF_REQUIRE_MSG(msgkey != (key_t)-1, "get_ftok failed");
20757718be8SEnji Cooper 
20857718be8SEnji Cooper 	sender_msqid = msgget(msgkey, IPC_CREAT | 0640);
20957718be8SEnji Cooper 	ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno);
21057718be8SEnji Cooper 	write_int("sender_msqid", sender_msqid);
21157718be8SEnji Cooper 
21257718be8SEnji Cooper 	if (did_sigsys) {
21357718be8SEnji Cooper 		atf_tc_skip("SYSV Message Queue not supported");
21457718be8SEnji Cooper 		return;
21557718be8SEnji Cooper 	}
21657718be8SEnji Cooper 
21757718be8SEnji Cooper 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
21857718be8SEnji Cooper 	"msgctl IPC_STAT 1: %d", errno);
21957718be8SEnji Cooper 
22057718be8SEnji Cooper 	print_msqid_ds(&m_ds, 0640);
22157718be8SEnji Cooper 
22257718be8SEnji Cooper 	m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600;
22357718be8SEnji Cooper 
22457718be8SEnji Cooper 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1,
22557718be8SEnji Cooper 	    "msgctl IPC_SET: %d", errno);
22657718be8SEnji Cooper 
22757718be8SEnji Cooper 	memset(&m_ds, 0, sizeof(m_ds));
22857718be8SEnji Cooper 
22957718be8SEnji Cooper 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
23057718be8SEnji Cooper 	    "msgctl IPC_STAT 2: %d", errno);
23157718be8SEnji Cooper 
23257718be8SEnji Cooper 	ATF_REQUIRE_MSG((m_ds.msg_perm.mode & 0777) == 0600,
23357718be8SEnji Cooper 	    "IPC_SET of mode didn't hold");
23457718be8SEnji Cooper 
23557718be8SEnji Cooper 	print_msqid_ds(&m_ds, 0600);
23657718be8SEnji Cooper 
237*20917cacSEric van Gyzen 	fflush(stdout);
238*20917cacSEric van Gyzen 
23957718be8SEnji Cooper 	switch ((child_pid = fork())) {
24057718be8SEnji Cooper 	case -1:
24157718be8SEnji Cooper 		atf_tc_fail("fork: %d", errno);
24257718be8SEnji Cooper 		return;
24357718be8SEnji Cooper 
24457718be8SEnji Cooper 	case 0:
24557718be8SEnji Cooper 		receiver();
24657718be8SEnji Cooper 		break;
24757718be8SEnji Cooper 
24857718be8SEnji Cooper 	default:
24957718be8SEnji Cooper 		break;
25057718be8SEnji Cooper 	}
25157718be8SEnji Cooper 
25257718be8SEnji Cooper 	for (loop = 0; loop < maxloop; loop++) {
25357718be8SEnji Cooper 		/*
25457718be8SEnji Cooper 		 * Send the first message to the receiver and wait for the ACK.
25557718be8SEnji Cooper 		 */
25657718be8SEnji Cooper 		m.mtype = MTYPE_1;
257fa82818fSAlan Somers 		strlcpy(m.mtext, m1_str, sizeof(m.mtext));
25857718be8SEnji Cooper 		ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN,
25957718be8SEnji Cooper 		    0) != -1, "sender: msgsnd 1: %d", errno);
26057718be8SEnji Cooper 
26157718be8SEnji Cooper 		ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN,
26257718be8SEnji Cooper 				       MTYPE_1_ACK, 0) == MESSAGE_TEXT_LEN,
26357718be8SEnji Cooper 		    "sender: msgrcv 1 ack: %d", errno);
26457718be8SEnji Cooper 
26557718be8SEnji Cooper 		print_msqid_ds(&m_ds, 0600);
26657718be8SEnji Cooper 
26757718be8SEnji Cooper 		/*
26857718be8SEnji Cooper 		 * Send the second message to the receiver and wait for the ACK.
26957718be8SEnji Cooper 		 */
27057718be8SEnji Cooper 		m.mtype = MTYPE_2;
271fa82818fSAlan Somers 		strlcpy(m.mtext, m2_str, sizeof(m.mtext));
27257718be8SEnji Cooper 		ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 0) != -1,
27357718be8SEnji Cooper 		    "sender: msgsnd 2: %d", errno);
27457718be8SEnji Cooper 
27557718be8SEnji Cooper 		ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN,
27657718be8SEnji Cooper 				       MTYPE_2_ACK, 0) == MESSAGE_TEXT_LEN,
27757718be8SEnji Cooper 		    "sender: msgrcv 2 ack: %d", errno);
27857718be8SEnji Cooper 	}
27957718be8SEnji Cooper 
28057718be8SEnji Cooper 	/*
28157718be8SEnji Cooper 	 * Wait for child to finish
28257718be8SEnji Cooper 	 */
283*20917cacSEric van Gyzen 	wait_result = wait(&c_status);
284*20917cacSEric van Gyzen 	ATF_REQUIRE_EQ_MSG(wait_result, child_pid, "wait returned %d (%s)",
285*20917cacSEric van Gyzen 	    wait_result, wait_result == -1 ? strerror(errno) : "");
286*20917cacSEric van Gyzen 	ATF_REQUIRE_MSG(WIFEXITED(c_status), "child abnormal exit: %d (sig %d)",
287*20917cacSEric van Gyzen 	    c_status, WTERMSIG(c_status));
288*20917cacSEric van Gyzen 	ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d",
289*20917cacSEric van Gyzen 	    WEXITSTATUS(c_status));
29057718be8SEnji Cooper 
291*20917cacSEric van Gyzen 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
292*20917cacSEric van Gyzen 	    "msgctl IPC_STAT: %d", errno);
29357718be8SEnji Cooper 
29457718be8SEnji Cooper 	print_msqid_ds(&m_ds, 0600);
29557718be8SEnji Cooper }
29657718be8SEnji Cooper 
ATF_TC_CLEANUP(msg,tc)29757718be8SEnji Cooper ATF_TC_CLEANUP(msg, tc)
29857718be8SEnji Cooper {
29957718be8SEnji Cooper 	int sender_msqid;
30057718be8SEnji Cooper 
30157718be8SEnji Cooper 	/*
30257718be8SEnji Cooper 	 * Remove the message queue if it exists.
30357718be8SEnji Cooper 	 */
30457718be8SEnji Cooper 	sender_msqid = read_int("sender_msqid");
30557718be8SEnji Cooper 	if (sender_msqid != -1)
30657718be8SEnji Cooper 		if (msgctl(sender_msqid, IPC_RMID, NULL) == -1)
30757718be8SEnji Cooper 			err(1, "msgctl IPC_RMID");
30857718be8SEnji Cooper }
30957718be8SEnji Cooper 
31057718be8SEnji Cooper void
print_msqid_ds(struct msqid_ds * mp,mode_t mode)3115e1e3ea2SBrooks Davis print_msqid_ds(struct msqid_ds *mp, mode_t mode)
31257718be8SEnji Cooper {
31357718be8SEnji Cooper 	uid_t uid = geteuid();
31457718be8SEnji Cooper 	gid_t gid = getegid();
31557718be8SEnji Cooper 
31657718be8SEnji Cooper 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
31757718be8SEnji Cooper 	    mp->msg_perm.uid, mp->msg_perm.gid,
31857718be8SEnji Cooper 	    mp->msg_perm.cuid, mp->msg_perm.cgid,
31957718be8SEnji Cooper 	    mp->msg_perm.mode & 0777);
32057718be8SEnji Cooper 
32157718be8SEnji Cooper 	printf("qnum %lu, qbytes %lu, lspid %d, lrpid %d\n",
32257718be8SEnji Cooper 	    mp->msg_qnum, (u_long)mp->msg_qbytes, mp->msg_lspid,
32357718be8SEnji Cooper 	    mp->msg_lrpid);
32457718be8SEnji Cooper 
32557718be8SEnji Cooper 	printf("stime: %s", ctime(&mp->msg_stime));
32657718be8SEnji Cooper 	printf("rtime: %s", ctime(&mp->msg_rtime));
32757718be8SEnji Cooper 	printf("ctime: %s", ctime(&mp->msg_ctime));
32857718be8SEnji Cooper 
32957718be8SEnji Cooper 	/*
33057718be8SEnji Cooper 	 * Sanity check a few things.
33157718be8SEnji Cooper 	 */
33257718be8SEnji Cooper 
33357718be8SEnji Cooper 	ATF_REQUIRE_MSG(mp->msg_perm.uid == uid && mp->msg_perm.cuid == uid,
33457718be8SEnji Cooper 	    "uid mismatch");
33557718be8SEnji Cooper 
33657718be8SEnji Cooper 	ATF_REQUIRE_MSG(mp->msg_perm.gid == gid && mp->msg_perm.cgid == gid,
33757718be8SEnji Cooper 	    "gid mismatch");
33857718be8SEnji Cooper 
33957718be8SEnji Cooper 	ATF_REQUIRE_MSG((mp->msg_perm.mode & 0777) == mode, "mode mismatch");
34057718be8SEnji Cooper }
34157718be8SEnji Cooper 
34257718be8SEnji Cooper void
receiver(void)3435e1e3ea2SBrooks Davis receiver(void)
34457718be8SEnji Cooper {
3455e1e3ea2SBrooks Davis 	struct testmsg m;
34657718be8SEnji Cooper 	int msqid, loop;
34757718be8SEnji Cooper 
34857718be8SEnji Cooper 	if ((msqid = msgget(msgkey, 0)) == -1)
34957718be8SEnji Cooper 		err(1, "receiver: msgget");
35057718be8SEnji Cooper 
35157718be8SEnji Cooper 	for (loop = 0; loop < maxloop; loop++) {
35257718be8SEnji Cooper 		/*
35357718be8SEnji Cooper 		 * Receive the first message, print it, and send an ACK.
35457718be8SEnji Cooper 		 */
35557718be8SEnji Cooper 		if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_1, 0) != MESSAGE_TEXT_LEN)
35657718be8SEnji Cooper 			err(1, "receiver: msgrcv 1");
35757718be8SEnji Cooper 
35857718be8SEnji Cooper 		printf("%s\n", m.mtext);
35957718be8SEnji Cooper 		if (strcmp(m.mtext, m1_str) != 0)
360*20917cacSEric van Gyzen 			errx(1, "receiver: message 1 data isn't correct");
36157718be8SEnji Cooper 
36257718be8SEnji Cooper 		m.mtype = MTYPE_1_ACK;
36357718be8SEnji Cooper 
36457718be8SEnji Cooper 		if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1)
36557718be8SEnji Cooper 			err(1, "receiver: msgsnd ack 1");
36657718be8SEnji Cooper 
36757718be8SEnji Cooper 		/*
36857718be8SEnji Cooper 		 * Receive the second message, print it, and send an ACK.
36957718be8SEnji Cooper 		 */
37057718be8SEnji Cooper 
37157718be8SEnji Cooper 		if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_2, 0) != MESSAGE_TEXT_LEN)
37257718be8SEnji Cooper 			err(1, "receiver: msgrcv 2");
37357718be8SEnji Cooper 
37457718be8SEnji Cooper 		printf("%s\n", m.mtext);
37557718be8SEnji Cooper 		if (strcmp(m.mtext, m2_str) != 0)
376*20917cacSEric van Gyzen 			errx(1, "receiver: message 2 data isn't correct");
37757718be8SEnji Cooper 
37857718be8SEnji Cooper 		m.mtype = MTYPE_2_ACK;
37957718be8SEnji Cooper 
38057718be8SEnji Cooper 		if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1)
38157718be8SEnji Cooper 			err(1, "receiver: msgsnd ack 2");
38257718be8SEnji Cooper 	}
38357718be8SEnji Cooper 
38457718be8SEnji Cooper 	exit(0);
38557718be8SEnji Cooper }
38657718be8SEnji Cooper 
38757718be8SEnji Cooper /*
38857718be8SEnji Cooper  * Test the SVID-compatible Semaphore facility.
38957718be8SEnji Cooper  */
39057718be8SEnji Cooper 
39157718be8SEnji Cooper ATF_TC_WITH_CLEANUP(sem);
ATF_TC_HEAD(sem,tc)39257718be8SEnji Cooper ATF_TC_HEAD(sem, tc)
39357718be8SEnji Cooper {
39457718be8SEnji Cooper 
39557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "3");
39657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing");
39757718be8SEnji Cooper }
39857718be8SEnji Cooper 
ATF_TC_BODY(sem,tc)39957718be8SEnji Cooper ATF_TC_BODY(sem, tc)
40057718be8SEnji Cooper {
40157718be8SEnji Cooper 	struct sigaction sa;
40257718be8SEnji Cooper 	union semun sun;
40357718be8SEnji Cooper 	struct semid_ds s_ds;
40457718be8SEnji Cooper 	int sender_semid;
40557718be8SEnji Cooper 	int i;
40657718be8SEnji Cooper 	int c_status;
407*20917cacSEric van Gyzen 	int child_count;
408*20917cacSEric van Gyzen 	pid_t wait_result;
40957718be8SEnji Cooper 
41057718be8SEnji Cooper 	/*
41157718be8SEnji Cooper 	 * Install a SIGSYS handler so that we can exit gracefully if
41257718be8SEnji Cooper 	 * System V Semaphore support isn't in the kernel.
41357718be8SEnji Cooper 	 */
41457718be8SEnji Cooper 	did_sigsys = 0;
41557718be8SEnji Cooper 	sa.sa_handler = sigsys_handler;
41657718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
41757718be8SEnji Cooper 	sa.sa_flags = 0;
41857718be8SEnji Cooper 	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
41957718be8SEnji Cooper 	    "sigaction SIGSYS: %d", errno);
42057718be8SEnji Cooper 
42157718be8SEnji Cooper 	semkey = get_ftok(4160);
42257718be8SEnji Cooper 	ATF_REQUIRE_MSG(semkey != (key_t)-1, "get_ftok failed");
42357718be8SEnji Cooper 
42457718be8SEnji Cooper 	sender_semid = semget(semkey, 1, IPC_CREAT | 0640);
42557718be8SEnji Cooper 	ATF_REQUIRE_MSG(sender_semid != -1, "semget: %d", errno);
42657718be8SEnji Cooper 	write_int("sender_semid", sender_semid);
42757718be8SEnji Cooper 
42857718be8SEnji Cooper 	if (did_sigsys) {
42957718be8SEnji Cooper 		atf_tc_skip("SYSV Semaphore not supported");
43057718be8SEnji Cooper 		return;
43157718be8SEnji Cooper 	}
43257718be8SEnji Cooper 
43357718be8SEnji Cooper 	sun.buf = &s_ds;
43457718be8SEnji Cooper 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
43557718be8SEnji Cooper 	    "semctl IPC_STAT: %d", errno);
43657718be8SEnji Cooper 
43757718be8SEnji Cooper 	print_semid_ds(&s_ds, 0640);
43857718be8SEnji Cooper 
43957718be8SEnji Cooper 	s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600;
44057718be8SEnji Cooper 
44157718be8SEnji Cooper 	sun.buf = &s_ds;
44257718be8SEnji Cooper 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_SET, sun) != -1,
44357718be8SEnji Cooper 	    "semctl IPC_SET: %d", errno);
44457718be8SEnji Cooper 
44557718be8SEnji Cooper 	memset(&s_ds, 0, sizeof(s_ds));
44657718be8SEnji Cooper 
44757718be8SEnji Cooper 	sun.buf = &s_ds;
44857718be8SEnji Cooper 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
44957718be8SEnji Cooper 	    "semctl IPC_STAT: %d", errno);
45057718be8SEnji Cooper 
45157718be8SEnji Cooper 	ATF_REQUIRE_MSG((s_ds.sem_perm.mode & 0777) == 0600,
45257718be8SEnji Cooper 	    "IPC_SET of mode didn't hold");
45357718be8SEnji Cooper 
45457718be8SEnji Cooper 	print_semid_ds(&s_ds, 0600);
45557718be8SEnji Cooper 
456*20917cacSEric van Gyzen 	fflush(stdout);
457*20917cacSEric van Gyzen 
45857718be8SEnji Cooper 	for (child_count = 0; child_count < 5; child_count++) {
45957718be8SEnji Cooper 		switch ((child_pid = fork())) {
46057718be8SEnji Cooper 		case -1:
46157718be8SEnji Cooper 			atf_tc_fail("fork: %d", errno);
46257718be8SEnji Cooper 			return;
46357718be8SEnji Cooper 
46457718be8SEnji Cooper 		case 0:
46557718be8SEnji Cooper 			waiter();
46657718be8SEnji Cooper 			break;
46757718be8SEnji Cooper 
46857718be8SEnji Cooper 		default:
46957718be8SEnji Cooper 			break;
47057718be8SEnji Cooper 		}
47157718be8SEnji Cooper 	}
47257718be8SEnji Cooper 
47357718be8SEnji Cooper 	/*
47457718be8SEnji Cooper 	 * Wait for all of the waiters to be attempting to acquire the
47557718be8SEnji Cooper 	 * semaphore.
47657718be8SEnji Cooper 	 */
47757718be8SEnji Cooper 	for (;;) {
47857718be8SEnji Cooper 		i = semctl(sender_semid, 0, GETNCNT);
47957718be8SEnji Cooper 		if (i == -1)
48057718be8SEnji Cooper 			atf_tc_fail("semctl GETNCNT: %d", i);
48157718be8SEnji Cooper 		if (i == 5)
48257718be8SEnji Cooper 			break;
48357718be8SEnji Cooper 	}
48457718be8SEnji Cooper 
48557718be8SEnji Cooper 	/*
48657718be8SEnji Cooper 	 * Now set the thundering herd in motion by initializing the
48757718be8SEnji Cooper 	 * semaphore to the value 1.
48857718be8SEnji Cooper 	 */
48957718be8SEnji Cooper 	sun.val = 1;
49057718be8SEnji Cooper 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, SETVAL, sun) != -1,
49157718be8SEnji Cooper 	    "sender: semctl SETVAL to 1: %d", errno);
49257718be8SEnji Cooper 
49357718be8SEnji Cooper 	/*
49457718be8SEnji Cooper 	 * Wait for all children to finish
49557718be8SEnji Cooper 	 */
496*20917cacSEric van Gyzen 	while (child_count-- > 0) {
497*20917cacSEric van Gyzen 		wait_result = wait(&c_status);
498*20917cacSEric van Gyzen 		ATF_REQUIRE_MSG(wait_result != -1, "wait failed: %s",
499*20917cacSEric van Gyzen 		    strerror(errno));
500*20917cacSEric van Gyzen 		ATF_REQUIRE_MSG(WIFEXITED(c_status),
501*20917cacSEric van Gyzen 		    "child abnormal exit: %d (sig %d)",
502*20917cacSEric van Gyzen 		    c_status, WTERMSIG(c_status));
503*20917cacSEric van Gyzen 		ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d",
50457718be8SEnji Cooper 		    WEXITSTATUS(c_status));
505*20917cacSEric van Gyzen 
50657718be8SEnji Cooper 		sun.buf = &s_ds;
507*20917cacSEric van Gyzen 		ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
50857718be8SEnji Cooper 		    "semctl IPC_STAT: %d", errno);
50957718be8SEnji Cooper 
51057718be8SEnji Cooper 		print_semid_ds(&s_ds, 0600);
51157718be8SEnji Cooper 	}
51257718be8SEnji Cooper }
51357718be8SEnji Cooper 
ATF_TC_CLEANUP(sem,tc)51457718be8SEnji Cooper ATF_TC_CLEANUP(sem, tc)
51557718be8SEnji Cooper {
51657718be8SEnji Cooper 	int sender_semid;
51757718be8SEnji Cooper 
51857718be8SEnji Cooper 	/*
51957718be8SEnji Cooper 	 * Remove the semaphore if it exists
52057718be8SEnji Cooper 	 */
52157718be8SEnji Cooper 	sender_semid = read_int("sender_semid");
52257718be8SEnji Cooper 	if (sender_semid != -1)
52357718be8SEnji Cooper 		if (semctl(sender_semid, 0, IPC_RMID) == -1)
52457718be8SEnji Cooper 			err(1, "semctl IPC_RMID");
52557718be8SEnji Cooper }
52657718be8SEnji Cooper 
52757718be8SEnji Cooper void
print_semid_ds(struct semid_ds * sp,mode_t mode)5285e1e3ea2SBrooks Davis print_semid_ds(struct semid_ds *sp, mode_t mode)
52957718be8SEnji Cooper {
53057718be8SEnji Cooper 	uid_t uid = geteuid();
53157718be8SEnji Cooper 	gid_t gid = getegid();
53257718be8SEnji Cooper 
53357718be8SEnji Cooper 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
53457718be8SEnji Cooper 	    sp->sem_perm.uid, sp->sem_perm.gid,
53557718be8SEnji Cooper 	    sp->sem_perm.cuid, sp->sem_perm.cgid,
53657718be8SEnji Cooper 	    sp->sem_perm.mode & 0777);
53757718be8SEnji Cooper 
53857718be8SEnji Cooper 	printf("nsems %u\n", sp->sem_nsems);
53957718be8SEnji Cooper 
54057718be8SEnji Cooper 	printf("otime: %s", ctime(&sp->sem_otime));
54157718be8SEnji Cooper 	printf("ctime: %s", ctime(&sp->sem_ctime));
54257718be8SEnji Cooper 
54357718be8SEnji Cooper 	/*
54457718be8SEnji Cooper 	 * Sanity check a few things.
54557718be8SEnji Cooper 	 */
54657718be8SEnji Cooper 
54757718be8SEnji Cooper 	ATF_REQUIRE_MSG(sp->sem_perm.uid == uid && sp->sem_perm.cuid == uid,
54857718be8SEnji Cooper 	    "uid mismatch");
54957718be8SEnji Cooper 
55057718be8SEnji Cooper 	ATF_REQUIRE_MSG(sp->sem_perm.gid == gid && sp->sem_perm.cgid == gid,
55157718be8SEnji Cooper 	    "gid mismatch");
55257718be8SEnji Cooper 
55357718be8SEnji Cooper 	ATF_REQUIRE_MSG((sp->sem_perm.mode & 0777) == mode,
55457718be8SEnji Cooper 	    "mode mismatch %o != %o", (sp->sem_perm.mode & 0777), mode);
55557718be8SEnji Cooper }
55657718be8SEnji Cooper 
55757718be8SEnji Cooper void
waiter(void)5585e1e3ea2SBrooks Davis waiter(void)
55957718be8SEnji Cooper {
56057718be8SEnji Cooper 	struct sembuf s;
56157718be8SEnji Cooper 	int semid;
56257718be8SEnji Cooper 
56357718be8SEnji Cooper 	if ((semid = semget(semkey, 1, 0)) == -1)
56457718be8SEnji Cooper 		err(1, "waiter: semget");
56557718be8SEnji Cooper 
56657718be8SEnji Cooper 	/*
56757718be8SEnji Cooper 	 * Attempt to acquire the semaphore.
56857718be8SEnji Cooper 	 */
56957718be8SEnji Cooper 	s.sem_num = 0;
57057718be8SEnji Cooper 	s.sem_op = -1;
57157718be8SEnji Cooper 	s.sem_flg = SEM_UNDO;
57257718be8SEnji Cooper 
57357718be8SEnji Cooper 	if (semop(semid, &s, 1) == -1)
57457718be8SEnji Cooper 		err(1, "waiter: semop -1");
57557718be8SEnji Cooper 
57657718be8SEnji Cooper 	printf("WOO!  GOT THE SEMAPHORE!\n");
577*20917cacSEric van Gyzen 	usleep(10000);
57857718be8SEnji Cooper 
57957718be8SEnji Cooper 	/*
58057718be8SEnji Cooper 	 * Release the semaphore and exit.
58157718be8SEnji Cooper 	 */
58257718be8SEnji Cooper 	s.sem_num = 0;
58357718be8SEnji Cooper 	s.sem_op = 1;
58457718be8SEnji Cooper 	s.sem_flg = SEM_UNDO;
58557718be8SEnji Cooper 
58657718be8SEnji Cooper 	if (semop(semid, &s, 1) == -1)
58757718be8SEnji Cooper 		err(1, "waiter: semop +1");
58857718be8SEnji Cooper 
58957718be8SEnji Cooper 	exit(0);
59057718be8SEnji Cooper }
59157718be8SEnji Cooper 
59257718be8SEnji Cooper /*
59357718be8SEnji Cooper  * Test the SVID-compatible Shared Memory facility.
59457718be8SEnji Cooper  */
59557718be8SEnji Cooper 
59657718be8SEnji Cooper ATF_TC_WITH_CLEANUP(shm);
ATF_TC_HEAD(shm,tc)59757718be8SEnji Cooper ATF_TC_HEAD(shm, tc)
59857718be8SEnji Cooper {
59957718be8SEnji Cooper 
60057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "3");
60157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks sysv shared memory");
60257718be8SEnji Cooper }
60357718be8SEnji Cooper 
ATF_TC_BODY(shm,tc)60457718be8SEnji Cooper ATF_TC_BODY(shm, tc)
60557718be8SEnji Cooper {
60657718be8SEnji Cooper 	struct sigaction sa;
60757718be8SEnji Cooper 	struct shmid_ds s_ds;
60857718be8SEnji Cooper 	char *shm_buf;
60957718be8SEnji Cooper 	int sender_shmid;
61057718be8SEnji Cooper 	int c_status;
611*20917cacSEric van Gyzen 	pid_t wait_result;
61257718be8SEnji Cooper 
61357718be8SEnji Cooper 	/*
61457718be8SEnji Cooper 	 * Install a SIGSYS handler so that we can exit gracefully if
61557718be8SEnji Cooper 	 * System V Shared Memory support isn't in the kernel.
61657718be8SEnji Cooper 	 */
61757718be8SEnji Cooper 	did_sigsys = 0;
61857718be8SEnji Cooper 	sa.sa_handler = sigsys_handler;
61957718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
62057718be8SEnji Cooper 	sa.sa_flags = 0;
62157718be8SEnji Cooper 	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
62257718be8SEnji Cooper 	    "sigaction SIGSYS: %d", errno);
62357718be8SEnji Cooper 
62457718be8SEnji Cooper 	pgsize = sysconf(_SC_PAGESIZE);
62557718be8SEnji Cooper 
62657718be8SEnji Cooper 	shmkey = get_ftok(4160);
62757718be8SEnji Cooper 	ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed");
62857718be8SEnji Cooper 
62957718be8SEnji Cooper 	ATF_REQUIRE_MSG((sender_shmid = shmget(shmkey, pgsize,
63057718be8SEnji Cooper 					       IPC_CREAT | 0640)) != -1,
63157718be8SEnji Cooper 	    "shmget: %d", errno);
63257718be8SEnji Cooper 	write_int("sender_shmid", sender_shmid);
63357718be8SEnji Cooper 
63457718be8SEnji Cooper 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1,
63557718be8SEnji Cooper 	    "shmctl IPC_STAT: %d", errno);
63657718be8SEnji Cooper 
63757718be8SEnji Cooper 	print_shmid_ds(&s_ds, 0640);
63857718be8SEnji Cooper 
63957718be8SEnji Cooper 	s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600;
64057718be8SEnji Cooper 
64157718be8SEnji Cooper 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_SET, &s_ds) != -1,
64257718be8SEnji Cooper 	    "shmctl IPC_SET: %d", errno);
64357718be8SEnji Cooper 
64457718be8SEnji Cooper 	memset(&s_ds, 0, sizeof(s_ds));
64557718be8SEnji Cooper 
64657718be8SEnji Cooper 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1,
64757718be8SEnji Cooper 	    "shmctl IPC_STAT: %d", errno);
64857718be8SEnji Cooper 
64957718be8SEnji Cooper 	ATF_REQUIRE_MSG((s_ds.shm_perm.mode & 0777) == 0600,
65057718be8SEnji Cooper 	    "IPC_SET of mode didn't hold");
65157718be8SEnji Cooper 
65257718be8SEnji Cooper 	print_shmid_ds(&s_ds, 0600);
65357718be8SEnji Cooper 
65457718be8SEnji Cooper 	shm_buf = shmat(sender_shmid, NULL, 0);
65557718be8SEnji Cooper 	ATF_REQUIRE_MSG(shm_buf != (void *) -1, "sender: shmat: %d", errno);
65657718be8SEnji Cooper 
65757718be8SEnji Cooper 	/*
65857718be8SEnji Cooper 	 * Write the test pattern into the shared memory buffer.
65957718be8SEnji Cooper 	 */
66057718be8SEnji Cooper 	strcpy(shm_buf, m2_str);
66157718be8SEnji Cooper 
662*20917cacSEric van Gyzen 	fflush(stdout);
663*20917cacSEric van Gyzen 
66457718be8SEnji Cooper 	switch ((child_pid = fork())) {
66557718be8SEnji Cooper 	case -1:
66657718be8SEnji Cooper 		atf_tc_fail("fork: %d", errno);
66757718be8SEnji Cooper 		return;
66857718be8SEnji Cooper 
66957718be8SEnji Cooper 	case 0:
67057718be8SEnji Cooper 		sharer();
67157718be8SEnji Cooper 		break;
67257718be8SEnji Cooper 
67357718be8SEnji Cooper 	default:
67457718be8SEnji Cooper 		break;
67557718be8SEnji Cooper 	}
67657718be8SEnji Cooper 
67757718be8SEnji Cooper 	/*
67857718be8SEnji Cooper 	 * Wait for child to finish
67957718be8SEnji Cooper 	 */
680*20917cacSEric van Gyzen 	wait_result = wait(&c_status);
681*20917cacSEric van Gyzen 	ATF_REQUIRE_EQ_MSG(wait_result, child_pid, "wait returned %d (%s)",
682*20917cacSEric van Gyzen 	    wait_result, wait_result == -1 ? strerror(errno) : "");
683*20917cacSEric van Gyzen 	ATF_REQUIRE_MSG(WIFEXITED(c_status), "child abnormal exit: %d (sig %d)",
684*20917cacSEric van Gyzen 	    c_status, WTERMSIG(c_status));
685*20917cacSEric van Gyzen 	ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d",
686*20917cacSEric van Gyzen 	    WEXITSTATUS(c_status));
68757718be8SEnji Cooper 
688*20917cacSEric van Gyzen 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1,
68957718be8SEnji Cooper 	    "shmctl IPC_STAT: %d", errno);
69057718be8SEnji Cooper 
69157718be8SEnji Cooper 	print_shmid_ds(&s_ds, 0600);
69257718be8SEnji Cooper }
69357718be8SEnji Cooper 
694ea7e7006SKonstantin Belousov static void
shmid_cleanup(const char * name)695ea7e7006SKonstantin Belousov shmid_cleanup(const char *name)
69657718be8SEnji Cooper {
697ea7e7006SKonstantin Belousov 	int shmid;
69857718be8SEnji Cooper 
69957718be8SEnji Cooper 	/*
70057718be8SEnji Cooper 	 * Remove the shared memory area if it exists.
70157718be8SEnji Cooper 	 */
702ea7e7006SKonstantin Belousov 	shmid = read_int(name);
703ea7e7006SKonstantin Belousov 	if (shmid != -1) {
704ea7e7006SKonstantin Belousov 		if (shmctl(shmid, IPC_RMID, NULL) == -1)
70557718be8SEnji Cooper 			err(1, "shmctl IPC_RMID");
70657718be8SEnji Cooper 	}
707ea7e7006SKonstantin Belousov }
708ea7e7006SKonstantin Belousov 
ATF_TC_CLEANUP(shm,tc)709ea7e7006SKonstantin Belousov ATF_TC_CLEANUP(shm, tc)
710ea7e7006SKonstantin Belousov {
711ea7e7006SKonstantin Belousov 
712ea7e7006SKonstantin Belousov 	shmid_cleanup("sender_shmid");
713ea7e7006SKonstantin Belousov }
71457718be8SEnji Cooper 
71557718be8SEnji Cooper void
print_shmid_ds(struct shmid_ds * sp,mode_t mode)7165e1e3ea2SBrooks Davis print_shmid_ds(struct shmid_ds *sp, mode_t mode)
71757718be8SEnji Cooper {
71857718be8SEnji Cooper 	uid_t uid = geteuid();
71957718be8SEnji Cooper 	gid_t gid = getegid();
72057718be8SEnji Cooper 
72157718be8SEnji Cooper 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
72257718be8SEnji Cooper 	    sp->shm_perm.uid, sp->shm_perm.gid,
72357718be8SEnji Cooper 	    sp->shm_perm.cuid, sp->shm_perm.cgid,
72457718be8SEnji Cooper 	    sp->shm_perm.mode & 0777);
72557718be8SEnji Cooper 
72657718be8SEnji Cooper 	printf("segsz %lu, lpid %d, cpid %d, nattch %u\n",
72757718be8SEnji Cooper 	    (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid,
72857718be8SEnji Cooper 	    sp->shm_nattch);
72957718be8SEnji Cooper 
73057718be8SEnji Cooper 	printf("atime: %s", ctime(&sp->shm_atime));
73157718be8SEnji Cooper 	printf("dtime: %s", ctime(&sp->shm_dtime));
73257718be8SEnji Cooper 	printf("ctime: %s", ctime(&sp->shm_ctime));
73357718be8SEnji Cooper 
73457718be8SEnji Cooper 	/*
73557718be8SEnji Cooper 	 * Sanity check a few things.
73657718be8SEnji Cooper 	 */
73757718be8SEnji Cooper 
73857718be8SEnji Cooper 	ATF_REQUIRE_MSG(sp->shm_perm.uid == uid && sp->shm_perm.cuid == uid,
73957718be8SEnji Cooper 	    "uid mismatch");
74057718be8SEnji Cooper 
74157718be8SEnji Cooper 	ATF_REQUIRE_MSG(sp->shm_perm.gid == gid && sp->shm_perm.cgid == gid,
74257718be8SEnji Cooper 	    "gid mismatch");
74357718be8SEnji Cooper 
74457718be8SEnji Cooper 	ATF_REQUIRE_MSG((sp->shm_perm.mode & 0777) == mode, "mode mismatch");
74557718be8SEnji Cooper }
74657718be8SEnji Cooper 
74757718be8SEnji Cooper void
sharer(void)7485e1e3ea2SBrooks Davis sharer(void)
74957718be8SEnji Cooper {
75057718be8SEnji Cooper 	int shmid;
75157718be8SEnji Cooper 	void *shm_buf;
75257718be8SEnji Cooper 
75357718be8SEnji Cooper 	shmid = shmget(shmkey, pgsize, 0);
754*20917cacSEric van Gyzen 	if (shmid == -1)
755*20917cacSEric van Gyzen 		err(1, "receiver: shmget");
75657718be8SEnji Cooper 
75757718be8SEnji Cooper 	shm_buf = shmat(shmid, NULL, 0);
758*20917cacSEric van Gyzen 	if (shm_buf == (void *) -1)
759*20917cacSEric van Gyzen 		err(1, "receiver: shmat");
76057718be8SEnji Cooper 
76157718be8SEnji Cooper 	printf("%s\n", (const char *)shm_buf);
76257718be8SEnji Cooper 
763*20917cacSEric van Gyzen 	if (strcmp((const char *)shm_buf, m2_str) != 0)
764*20917cacSEric van Gyzen 		errx(1, "receiver: data isn't correct");
76557718be8SEnji Cooper 
76657718be8SEnji Cooper 	exit(0);
76757718be8SEnji Cooper }
76857718be8SEnji Cooper 
769ea7e7006SKonstantin Belousov #ifdef SHM_REMAP
770ea7e7006SKonstantin Belousov ATF_TC_WITH_CLEANUP(shm_remap);
ATF_TC_HEAD(shm_remap,tc)771ea7e7006SKonstantin Belousov ATF_TC_HEAD(shm_remap, tc)
772ea7e7006SKonstantin Belousov {
773ea7e7006SKonstantin Belousov 
774ea7e7006SKonstantin Belousov 	atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP");
775ea7e7006SKonstantin Belousov }
776ea7e7006SKonstantin Belousov 
ATF_TC_BODY(shm_remap,tc)777ea7e7006SKonstantin Belousov ATF_TC_BODY(shm_remap, tc)
778ea7e7006SKonstantin Belousov {
779ea7e7006SKonstantin Belousov 	char *shm_buf;
780ea7e7006SKonstantin Belousov 	int shmid_remap;
781ea7e7006SKonstantin Belousov 
782ea7e7006SKonstantin Belousov 	pgsize = sysconf(_SC_PAGESIZE);
783ea7e7006SKonstantin Belousov 
784ea7e7006SKonstantin Belousov 	shmkey = get_ftok(4160);
785ea7e7006SKonstantin Belousov 	ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed");
786ea7e7006SKonstantin Belousov 
787ea7e7006SKonstantin Belousov 	ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize,
788ea7e7006SKonstantin Belousov 	    IPC_CREAT | 0640)) != -1, "shmget: %d", errno);
789ea7e7006SKonstantin Belousov 	write_int("shmid_remap", shmid_remap);
790ea7e7006SKonstantin Belousov 
791ea7e7006SKonstantin Belousov 	ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
792ea7e7006SKonstantin Belousov 	    MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno);
793ea7e7006SKonstantin Belousov 
794ea7e7006SKonstantin Belousov 	ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1,
795ea7e7006SKonstantin Belousov 	    "shmat without MAP_REMAP succeeded");
796ea7e7006SKonstantin Belousov 	ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf,
797ea7e7006SKonstantin Belousov 	    "shmat(SHM_REMAP): %d", errno);
798ea7e7006SKonstantin Belousov }
799ea7e7006SKonstantin Belousov 
ATF_TC_CLEANUP(shm_remap,tc)800ea7e7006SKonstantin Belousov ATF_TC_CLEANUP(shm_remap, tc)
801ea7e7006SKonstantin Belousov {
802ea7e7006SKonstantin Belousov 
803ea7e7006SKonstantin Belousov 	shmid_cleanup("shmid_remap");
804ea7e7006SKonstantin Belousov }
805ea7e7006SKonstantin Belousov #endif	/* SHM_REMAP */
806ea7e7006SKonstantin Belousov 
ATF_TP_ADD_TCS(tp)80757718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
80857718be8SEnji Cooper {
80957718be8SEnji Cooper 
81057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, msg);
81157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sem);
81257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, shm);
813ea7e7006SKonstantin Belousov #ifdef SHM_REMAP
814ea7e7006SKonstantin Belousov 	ATF_TP_ADD_TC(tp, shm_remap);
815ea7e7006SKonstantin Belousov #endif
81657718be8SEnji Cooper 
81757718be8SEnji Cooper 	return atf_no_error();
81857718be8SEnji Cooper }
81957718be8SEnji Cooper 
820