Home | History | Annotate | Line # | Download | only in kernel
t_sysv.c revision 1.6
      1  1.6  christos /*	$NetBSD: t_sysv.c,v 1.6 2022/05/14 14:02:03 christos Exp $	*/
      2  1.1  pgoyette 
      3  1.1  pgoyette /*-
      4  1.1  pgoyette  * Copyright (c) 1999, 2007 The NetBSD Foundation, Inc.
      5  1.1  pgoyette  * All rights reserved.
      6  1.1  pgoyette  *
      7  1.1  pgoyette  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  pgoyette  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  1.1  pgoyette  * NASA Ames Research Center, and by Andrew Doran.
     10  1.1  pgoyette  *
     11  1.1  pgoyette  * Redistribution and use in source and binary forms, with or without
     12  1.1  pgoyette  * modification, are permitted provided that the following conditions
     13  1.1  pgoyette  * are met:
     14  1.1  pgoyette  * 1. Redistributions of source code must retain the above copyright
     15  1.1  pgoyette  *    notice, this list of conditions and the following disclaimer.
     16  1.1  pgoyette  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.1  pgoyette  *    notice, this list of conditions and the following disclaimer in the
     18  1.1  pgoyette  *    documentation and/or other materials provided with the distribution.
     19  1.1  pgoyette  *
     20  1.1  pgoyette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  1.1  pgoyette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  1.1  pgoyette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  1.1  pgoyette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  1.1  pgoyette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  1.1  pgoyette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  1.1  pgoyette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  1.1  pgoyette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  1.1  pgoyette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  1.1  pgoyette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  1.1  pgoyette  * POSSIBILITY OF SUCH DAMAGE.
     31  1.1  pgoyette  */
     32  1.1  pgoyette 
     33  1.1  pgoyette /*
     34  1.1  pgoyette  * Test the SVID-compatible Message Queue facility.
     35  1.1  pgoyette  */
     36  1.1  pgoyette 
     37  1.1  pgoyette #include <atf-c.h>
     38  1.1  pgoyette 
     39  1.1  pgoyette #include <err.h>
     40  1.1  pgoyette #include <errno.h>
     41  1.1  pgoyette #include <fcntl.h>
     42  1.1  pgoyette #include <signal.h>
     43  1.1  pgoyette #include <stdio.h>
     44  1.1  pgoyette #include <stdlib.h>
     45  1.1  pgoyette #include <string.h>
     46  1.1  pgoyette #include <time.h>
     47  1.1  pgoyette #include <unistd.h>
     48  1.1  pgoyette 
     49  1.1  pgoyette #include <sys/ipc.h>
     50  1.1  pgoyette #include <sys/msg.h>
     51  1.1  pgoyette #include <sys/param.h>
     52  1.1  pgoyette #include <sys/sem.h>
     53  1.1  pgoyette #include <sys/shm.h>
     54  1.1  pgoyette #include <sys/wait.h>
     55  1.1  pgoyette 
     56  1.6  christos volatile int did_sigsys;
     57  1.1  pgoyette 
     58  1.1  pgoyette void	sigsys_handler(int);
     59  1.1  pgoyette 
     60  1.2  pgoyette key_t	get_ftok(int);
     61  1.2  pgoyette 
     62  1.1  pgoyette void	print_msqid_ds(struct msqid_ds *, mode_t);
     63  1.1  pgoyette void	receiver(void);
     64  1.1  pgoyette 
     65  1.1  pgoyette void	print_semid_ds(struct semid_ds *, mode_t);
     66  1.1  pgoyette void	waiter(void);
     67  1.1  pgoyette 
     68  1.1  pgoyette void	print_shmid_ds(struct shmid_ds *, mode_t);
     69  1.1  pgoyette void	sharer(void);
     70  1.1  pgoyette 
     71  1.1  pgoyette #define	MESSAGE_TEXT_LEN	256
     72  1.1  pgoyette 
     73  1.5  pgoyette struct testmsg {
     74  1.1  pgoyette 	long	mtype;
     75  1.1  pgoyette 	char	mtext[MESSAGE_TEXT_LEN];
     76  1.1  pgoyette };
     77  1.1  pgoyette 
     78  1.1  pgoyette const char *m1_str = "California is overrated.";
     79  1.1  pgoyette const char *m2_str = "The quick brown fox jumped over the lazy dog.";
     80  1.1  pgoyette 
     81  1.1  pgoyette size_t	pgsize;
     82  1.1  pgoyette 
     83  1.1  pgoyette #define	MTYPE_1		1
     84  1.1  pgoyette #define	MTYPE_1_ACK	2
     85  1.1  pgoyette 
     86  1.1  pgoyette #define	MTYPE_2		3
     87  1.1  pgoyette #define	MTYPE_2_ACK	4
     88  1.1  pgoyette 
     89  1.1  pgoyette pid_t	child_pid;
     90  1.1  pgoyette 
     91  1.1  pgoyette key_t	msgkey, semkey, shmkey;
     92  1.1  pgoyette 
     93  1.1  pgoyette int	maxloop = 1;
     94  1.1  pgoyette 
     95  1.1  pgoyette union semun {
     96  1.1  pgoyette 	int	val;		/* value for SETVAL */
     97  1.1  pgoyette 	struct	semid_ds *buf;	/* buffer for IPC_{STAT,SET} */
     98  1.1  pgoyette 	u_short	*array;		/* array for GETALL & SETALL */
     99  1.1  pgoyette };
    100  1.1  pgoyette 
    101  1.1  pgoyette 
    102  1.4      jmmv /* Writes an integer to a file.  To be used from the body of the test
    103  1.4      jmmv  * cases below to pass any global identifiers to the cleanup routine. */
    104  1.4      jmmv static void
    105  1.4      jmmv write_int(const char *path, const int value)
    106  1.4      jmmv {
    107  1.4      jmmv 	int output;
    108  1.4      jmmv 
    109  1.4      jmmv 	output = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    110  1.4      jmmv 	ATF_REQUIRE_MSG(output != -1, "Failed to create %s", path);
    111  1.4      jmmv 	write(output, &value, sizeof(value));
    112  1.4      jmmv 	close(output);
    113  1.4      jmmv }
    114  1.4      jmmv 
    115  1.4      jmmv 
    116  1.4      jmmv /* Reads an integer from a file.  To be used from the cleanup routines
    117  1.4      jmmv  * of the test cases below. */
    118  1.4      jmmv static int
    119  1.4      jmmv read_int(const char *path)
    120  1.4      jmmv {
    121  1.6  christos 	int input, value;
    122  1.4      jmmv 
    123  1.4      jmmv 	input = open(path, O_RDONLY);
    124  1.4      jmmv 	if (input == -1)
    125  1.4      jmmv 		return -1;
    126  1.6  christos 
    127  1.6  christos 	read(input, &value, sizeof(value));
    128  1.6  christos 	return value;
    129  1.4      jmmv }
    130  1.4      jmmv 
    131  1.4      jmmv 
    132  1.1  pgoyette void
    133  1.1  pgoyette sigsys_handler(int signo)
    134  1.1  pgoyette {
    135  1.1  pgoyette 
    136  1.1  pgoyette 	did_sigsys = 1;
    137  1.1  pgoyette }
    138  1.1  pgoyette 
    139  1.2  pgoyette key_t get_ftok(int id)
    140  1.2  pgoyette {
    141  1.2  pgoyette 	int fd;
    142  1.2  pgoyette 	char token_key[64], token_dir[64];
    143  1.2  pgoyette 	char *tmpdir;
    144  1.2  pgoyette 	key_t key;
    145  1.2  pgoyette 
    146  1.2  pgoyette 	strlcpy(token_key, "/tmp/t_sysv.XXXXXX", sizeof(token_key));
    147  1.2  pgoyette 	tmpdir = mkdtemp(token_key);
    148  1.2  pgoyette 	ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp() failed: %d", errno);
    149  1.2  pgoyette 
    150  1.2  pgoyette 	strlcpy(token_dir, tmpdir, sizeof(token_dir));
    151  1.2  pgoyette 	strlcpy(token_key, tmpdir, sizeof(token_key));
    152  1.2  pgoyette 	strlcat(token_key, "/token_key", sizeof(token_key));
    153  1.2  pgoyette 
    154  1.2  pgoyette 	/* Create the file, since ftok() requires it to exist! */
    155  1.2  pgoyette 
    156  1.5  pgoyette 	fd = open(token_key, O_RDWR | O_CREAT | O_EXCL, 0600);
    157  1.2  pgoyette 	if (fd == -1) {
    158  1.2  pgoyette 		rmdir(tmpdir);
    159  1.2  pgoyette 		atf_tc_fail("open() of temp file failed: %d", errno);
    160  1.2  pgoyette 		return (key_t)-1;
    161  1.6  christos 	}
    162  1.6  christos 
    163  1.6  christos 	close(fd);
    164  1.2  pgoyette 
    165  1.2  pgoyette 	key = ftok(token_key, id);
    166  1.5  pgoyette 	ATF_REQUIRE_MSG(key != (key_t)-1, "ftok() failed");
    167  1.2  pgoyette 
    168  1.2  pgoyette 	ATF_REQUIRE_MSG(unlink(token_key) != -1, "unlink() failed: %d", errno);
    169  1.2  pgoyette 	ATF_REQUIRE_MSG(rmdir(token_dir) != -1, "rmdir() failed: %d", errno);
    170  1.2  pgoyette 
    171  1.2  pgoyette 	return key;
    172  1.2  pgoyette }
    173  1.2  pgoyette 
    174  1.2  pgoyette ATF_TC_WITH_CLEANUP(msg);
    175  1.1  pgoyette ATF_TC_HEAD(msg, tc)
    176  1.1  pgoyette {
    177  1.1  pgoyette 
    178  1.1  pgoyette 	atf_tc_set_md_var(tc, "timeout", "3");
    179  1.1  pgoyette 	atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing");
    180  1.1  pgoyette }
    181  1.1  pgoyette 
    182  1.1  pgoyette ATF_TC_BODY(msg, tc)
    183  1.1  pgoyette {
    184  1.1  pgoyette 	struct sigaction sa;
    185  1.1  pgoyette 	struct msqid_ds m_ds;
    186  1.5  pgoyette 	struct testmsg m;
    187  1.4      jmmv 	int sender_msqid;
    188  1.1  pgoyette 	int loop;
    189  1.1  pgoyette 	int c_status;
    190  1.6  christos 	pid_t wait_result;
    191  1.1  pgoyette 
    192  1.1  pgoyette 	/*
    193  1.1  pgoyette 	 * Install a SIGSYS handler so that we can exit gracefully if
    194  1.1  pgoyette 	 * System V Message Queue support isn't in the kernel.
    195  1.1  pgoyette 	 */
    196  1.1  pgoyette 	did_sigsys = 0;
    197  1.1  pgoyette 	sa.sa_handler = sigsys_handler;
    198  1.1  pgoyette 	sigemptyset(&sa.sa_mask);
    199  1.1  pgoyette 	sa.sa_flags = 0;
    200  1.1  pgoyette 	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
    201  1.1  pgoyette 	    "sigaction SIGSYS: %d", errno);
    202  1.1  pgoyette 
    203  1.2  pgoyette 	msgkey = get_ftok(4160);
    204  1.2  pgoyette 	ATF_REQUIRE_MSG(msgkey != (key_t)-1, "get_ftok failed");
    205  1.1  pgoyette 
    206  1.1  pgoyette 	sender_msqid = msgget(msgkey, IPC_CREAT | 0640);
    207  1.1  pgoyette 	ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno);
    208  1.4      jmmv 	write_int("sender_msqid", sender_msqid);
    209  1.1  pgoyette 
    210  1.1  pgoyette 	if (did_sigsys) {
    211  1.1  pgoyette 		atf_tc_skip("SYSV Message Queue not supported");
    212  1.1  pgoyette 		return;
    213  1.1  pgoyette 	}
    214  1.1  pgoyette 
    215  1.1  pgoyette 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
    216  1.1  pgoyette 	"msgctl IPC_STAT 1: %d", errno);
    217  1.1  pgoyette 
    218  1.1  pgoyette 	print_msqid_ds(&m_ds, 0640);
    219  1.1  pgoyette 
    220  1.1  pgoyette 	m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600;
    221  1.1  pgoyette 
    222  1.1  pgoyette 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1,
    223  1.1  pgoyette 	    "msgctl IPC_SET: %d", errno);
    224  1.1  pgoyette 
    225  1.1  pgoyette 	memset(&m_ds, 0, sizeof(m_ds));
    226  1.1  pgoyette 
    227  1.1  pgoyette 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
    228  1.1  pgoyette 	    "msgctl IPC_STAT 2: %d", errno);
    229  1.1  pgoyette 
    230  1.1  pgoyette 	ATF_REQUIRE_MSG((m_ds.msg_perm.mode & 0777) == 0600,
    231  1.1  pgoyette 	    "IPC_SET of mode didn't hold");
    232  1.1  pgoyette 
    233  1.1  pgoyette 	print_msqid_ds(&m_ds, 0600);
    234  1.1  pgoyette 
    235  1.6  christos 	fflush(stdout);
    236  1.6  christos 
    237  1.1  pgoyette 	switch ((child_pid = fork())) {
    238  1.1  pgoyette 	case -1:
    239  1.1  pgoyette 		atf_tc_fail("fork: %d", errno);
    240  1.1  pgoyette 		return;
    241  1.1  pgoyette 
    242  1.1  pgoyette 	case 0:
    243  1.1  pgoyette 		receiver();
    244  1.1  pgoyette 		break;
    245  1.1  pgoyette 
    246  1.1  pgoyette 	default:
    247  1.1  pgoyette 		break;
    248  1.1  pgoyette 	}
    249  1.1  pgoyette 
    250  1.1  pgoyette 	for (loop = 0; loop < maxloop; loop++) {
    251  1.1  pgoyette 		/*
    252  1.1  pgoyette 		 * Send the first message to the receiver and wait for the ACK.
    253  1.1  pgoyette 		 */
    254  1.1  pgoyette 		m.mtype = MTYPE_1;
    255  1.1  pgoyette 		strcpy(m.mtext, m1_str);
    256  1.3     skrll 		ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN,
    257  1.3     skrll 		    0) != -1, "sender: msgsnd 1: %d", errno);
    258  1.1  pgoyette 
    259  1.3     skrll 		ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN,
    260  1.6  christos 		    MTYPE_1_ACK, 0) == MESSAGE_TEXT_LEN,
    261  1.1  pgoyette 		    "sender: msgrcv 1 ack: %d", errno);
    262  1.1  pgoyette 
    263  1.1  pgoyette 		print_msqid_ds(&m_ds, 0600);
    264  1.1  pgoyette 
    265  1.1  pgoyette 		/*
    266  1.1  pgoyette 		 * Send the second message to the receiver and wait for the ACK.
    267  1.1  pgoyette 		 */
    268  1.1  pgoyette 		m.mtype = MTYPE_2;
    269  1.1  pgoyette 		strcpy(m.mtext, m2_str);
    270  1.6  christos 		ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 0)
    271  1.6  christos 		    != -1, "sender: msgsnd 2: %d", errno);
    272  1.1  pgoyette 
    273  1.3     skrll 		ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN,
    274  1.6  christos 		    MTYPE_2_ACK, 0) == MESSAGE_TEXT_LEN,
    275  1.1  pgoyette 		    "sender: msgrcv 2 ack: %d", errno);
    276  1.1  pgoyette 	}
    277  1.1  pgoyette 
    278  1.1  pgoyette 	/*
    279  1.1  pgoyette 	 * Wait for child to finish
    280  1.1  pgoyette 	 */
    281  1.6  christos 	wait_result = wait(&c_status);
    282  1.6  christos 	ATF_REQUIRE_EQ_MSG(wait_result, child_pid, "wait returned %d (%s)",
    283  1.6  christos 	    wait_result, wait_result == -1 ? strerror(errno) : "");
    284  1.6  christos 	ATF_REQUIRE_MSG(WIFEXITED(c_status), "child abnormal exit: %d (sig %d)",
    285  1.6  christos 	    c_status, WTERMSIG(c_status));
    286  1.6  christos 	ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d",
    287  1.6  christos 	    WEXITSTATUS(c_status));
    288  1.1  pgoyette 
    289  1.6  christos 	ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
    290  1.6  christos 	    "msgctl IPC_STAT: %d", errno);
    291  1.1  pgoyette 
    292  1.6  christos 	print_msqid_ds(&m_ds, 0600);
    293  1.1  pgoyette }
    294  1.1  pgoyette 
    295  1.2  pgoyette ATF_TC_CLEANUP(msg, tc)
    296  1.1  pgoyette {
    297  1.4      jmmv 	int sender_msqid;
    298  1.1  pgoyette 
    299  1.1  pgoyette 	/*
    300  1.2  pgoyette 	 * Remove the message queue if it exists.
    301  1.1  pgoyette 	 */
    302  1.4      jmmv 	sender_msqid = read_int("sender_msqid");
    303  1.6  christos 	if (sender_msqid == -1)
    304  1.6  christos 		return;
    305  1.6  christos 	if (msgctl(sender_msqid, IPC_RMID, NULL) == -1)
    306  1.6  christos 		err(EXIT_FAILURE, "msgctl IPC_RMID");
    307  1.1  pgoyette }
    308  1.1  pgoyette 
    309  1.1  pgoyette void
    310  1.5  pgoyette print_msqid_ds(struct msqid_ds *mp, mode_t mode)
    311  1.1  pgoyette {
    312  1.1  pgoyette 	uid_t uid = geteuid();
    313  1.1  pgoyette 	gid_t gid = getegid();
    314  1.1  pgoyette 
    315  1.1  pgoyette 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
    316  1.1  pgoyette 	    mp->msg_perm.uid, mp->msg_perm.gid,
    317  1.1  pgoyette 	    mp->msg_perm.cuid, mp->msg_perm.cgid,
    318  1.1  pgoyette 	    mp->msg_perm.mode & 0777);
    319  1.1  pgoyette 
    320  1.6  christos 	printf("qnum %lu, qbytes %ju, lspid %d, lrpid %d\n",
    321  1.6  christos 	    mp->msg_qnum, (uintmax_t)mp->msg_qbytes, mp->msg_lspid,
    322  1.1  pgoyette 	    mp->msg_lrpid);
    323  1.1  pgoyette 
    324  1.1  pgoyette 	printf("stime: %s", ctime(&mp->msg_stime));
    325  1.1  pgoyette 	printf("rtime: %s", ctime(&mp->msg_rtime));
    326  1.1  pgoyette 	printf("ctime: %s", ctime(&mp->msg_ctime));
    327  1.1  pgoyette 
    328  1.1  pgoyette 	/*
    329  1.1  pgoyette 	 * Sanity check a few things.
    330  1.1  pgoyette 	 */
    331  1.1  pgoyette 
    332  1.1  pgoyette 	ATF_REQUIRE_MSG(mp->msg_perm.uid == uid && mp->msg_perm.cuid == uid,
    333  1.1  pgoyette 	    "uid mismatch");
    334  1.1  pgoyette 
    335  1.1  pgoyette 	ATF_REQUIRE_MSG(mp->msg_perm.gid == gid && mp->msg_perm.cgid == gid,
    336  1.1  pgoyette 	    "gid mismatch");
    337  1.1  pgoyette 
    338  1.1  pgoyette 	ATF_REQUIRE_MSG((mp->msg_perm.mode & 0777) == mode, "mode mismatch");
    339  1.1  pgoyette }
    340  1.1  pgoyette 
    341  1.1  pgoyette void
    342  1.5  pgoyette receiver(void)
    343  1.1  pgoyette {
    344  1.5  pgoyette 	struct testmsg m;
    345  1.1  pgoyette 	int msqid, loop;
    346  1.1  pgoyette 
    347  1.1  pgoyette 	if ((msqid = msgget(msgkey, 0)) == -1)
    348  1.6  christos 		err(EXIT_FAILURE, "receiver: msgget");
    349  1.1  pgoyette 
    350  1.1  pgoyette 	for (loop = 0; loop < maxloop; loop++) {
    351  1.1  pgoyette 		/*
    352  1.1  pgoyette 		 * Receive the first message, print it, and send an ACK.
    353  1.1  pgoyette 		 */
    354  1.6  christos 		if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_1, 0)
    355  1.6  christos 		    != MESSAGE_TEXT_LEN)
    356  1.6  christos 			err(EXIT_FAILURE, "receiver: msgrcv 1");
    357  1.1  pgoyette 
    358  1.1  pgoyette 		printf("%s\n", m.mtext);
    359  1.1  pgoyette 		if (strcmp(m.mtext, m1_str) != 0)
    360  1.6  christos 			errx(EXIT_FAILURE,
    361  1.6  christos 			    "receiver: message 1 data isn't correct");
    362  1.1  pgoyette 
    363  1.1  pgoyette 		m.mtype = MTYPE_1_ACK;
    364  1.1  pgoyette 
    365  1.3     skrll 		if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1)
    366  1.6  christos 			err(EXIT_FAILURE, "receiver: msgsnd ack 1");
    367  1.1  pgoyette 
    368  1.1  pgoyette 		/*
    369  1.1  pgoyette 		 * Receive the second message, print it, and send an ACK.
    370  1.1  pgoyette 		 */
    371  1.1  pgoyette 
    372  1.6  christos 		if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_2, 0)
    373  1.6  christos 		    != MESSAGE_TEXT_LEN)
    374  1.6  christos 			err(EXIT_FAILURE, "receiver: msgrcv 2");
    375  1.1  pgoyette 
    376  1.1  pgoyette 		printf("%s\n", m.mtext);
    377  1.1  pgoyette 		if (strcmp(m.mtext, m2_str) != 0)
    378  1.6  christos 			errx(EXIT_FAILURE,
    379  1.6  christos 			    "receiver: message 2 data isn't correct");
    380  1.1  pgoyette 
    381  1.1  pgoyette 		m.mtype = MTYPE_2_ACK;
    382  1.1  pgoyette 
    383  1.3     skrll 		if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1)
    384  1.6  christos 			err(EXIT_FAILURE, "receiver: msgsnd ack 2");
    385  1.1  pgoyette 	}
    386  1.1  pgoyette 
    387  1.6  christos 	exit(EXIT_SUCCESS);
    388  1.1  pgoyette }
    389  1.1  pgoyette 
    390  1.1  pgoyette /*
    391  1.1  pgoyette  * Test the SVID-compatible Semaphore facility.
    392  1.1  pgoyette  */
    393  1.1  pgoyette 
    394  1.2  pgoyette ATF_TC_WITH_CLEANUP(sem);
    395  1.1  pgoyette ATF_TC_HEAD(sem, tc)
    396  1.1  pgoyette {
    397  1.1  pgoyette 
    398  1.1  pgoyette 	atf_tc_set_md_var(tc, "timeout", "3");
    399  1.1  pgoyette 	atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing");
    400  1.1  pgoyette }
    401  1.1  pgoyette 
    402  1.1  pgoyette ATF_TC_BODY(sem, tc)
    403  1.1  pgoyette {
    404  1.1  pgoyette 	struct sigaction sa;
    405  1.1  pgoyette 	union semun sun;
    406  1.1  pgoyette 	struct semid_ds s_ds;
    407  1.4      jmmv 	int sender_semid;
    408  1.1  pgoyette 	int i;
    409  1.1  pgoyette 	int c_status;
    410  1.6  christos 	int child_count;
    411  1.6  christos 	pid_t wait_result;
    412  1.1  pgoyette 
    413  1.1  pgoyette 	/*
    414  1.1  pgoyette 	 * Install a SIGSYS handler so that we can exit gracefully if
    415  1.1  pgoyette 	 * System V Semaphore support isn't in the kernel.
    416  1.1  pgoyette 	 */
    417  1.1  pgoyette 	did_sigsys = 0;
    418  1.1  pgoyette 	sa.sa_handler = sigsys_handler;
    419  1.1  pgoyette 	sigemptyset(&sa.sa_mask);
    420  1.1  pgoyette 	sa.sa_flags = 0;
    421  1.1  pgoyette 	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
    422  1.1  pgoyette 	    "sigaction SIGSYS: %d", errno);
    423  1.1  pgoyette 
    424  1.2  pgoyette 	semkey = get_ftok(4160);
    425  1.2  pgoyette 	ATF_REQUIRE_MSG(semkey != (key_t)-1, "get_ftok failed");
    426  1.1  pgoyette 
    427  1.1  pgoyette 	sender_semid = semget(semkey, 1, IPC_CREAT | 0640);
    428  1.1  pgoyette 	ATF_REQUIRE_MSG(sender_semid != -1, "semget: %d", errno);
    429  1.4      jmmv 	write_int("sender_semid", sender_semid);
    430  1.1  pgoyette 
    431  1.1  pgoyette 	if (did_sigsys) {
    432  1.1  pgoyette 		atf_tc_skip("SYSV Semaphore not supported");
    433  1.1  pgoyette 		return;
    434  1.1  pgoyette 	}
    435  1.1  pgoyette 
    436  1.1  pgoyette 	sun.buf = &s_ds;
    437  1.1  pgoyette 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
    438  1.1  pgoyette 	    "semctl IPC_STAT: %d", errno);
    439  1.1  pgoyette 
    440  1.1  pgoyette 	print_semid_ds(&s_ds, 0640);
    441  1.1  pgoyette 
    442  1.1  pgoyette 	s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600;
    443  1.1  pgoyette 
    444  1.1  pgoyette 	sun.buf = &s_ds;
    445  1.1  pgoyette 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_SET, sun) != -1,
    446  1.1  pgoyette 	    "semctl IPC_SET: %d", errno);
    447  1.1  pgoyette 
    448  1.1  pgoyette 	memset(&s_ds, 0, sizeof(s_ds));
    449  1.1  pgoyette 
    450  1.1  pgoyette 	sun.buf = &s_ds;
    451  1.1  pgoyette 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
    452  1.1  pgoyette 	    "semctl IPC_STAT: %d", errno);
    453  1.1  pgoyette 
    454  1.1  pgoyette 	ATF_REQUIRE_MSG((s_ds.sem_perm.mode & 0777) == 0600,
    455  1.1  pgoyette 	    "IPC_SET of mode didn't hold");
    456  1.1  pgoyette 
    457  1.1  pgoyette 	print_semid_ds(&s_ds, 0600);
    458  1.1  pgoyette 
    459  1.6  christos 	fflush(stdout);
    460  1.6  christos 
    461  1.1  pgoyette 	for (child_count = 0; child_count < 5; child_count++) {
    462  1.1  pgoyette 		switch ((child_pid = fork())) {
    463  1.1  pgoyette 		case -1:
    464  1.1  pgoyette 			atf_tc_fail("fork: %d", errno);
    465  1.1  pgoyette 			return;
    466  1.1  pgoyette 
    467  1.1  pgoyette 		case 0:
    468  1.1  pgoyette 			waiter();
    469  1.1  pgoyette 			break;
    470  1.1  pgoyette 
    471  1.1  pgoyette 		default:
    472  1.1  pgoyette 			break;
    473  1.1  pgoyette 		}
    474  1.1  pgoyette 	}
    475  1.1  pgoyette 
    476  1.1  pgoyette 	/*
    477  1.1  pgoyette 	 * Wait for all of the waiters to be attempting to acquire the
    478  1.1  pgoyette 	 * semaphore.
    479  1.1  pgoyette 	 */
    480  1.1  pgoyette 	for (;;) {
    481  1.1  pgoyette 		i = semctl(sender_semid, 0, GETNCNT);
    482  1.1  pgoyette 		if (i == -1)
    483  1.1  pgoyette 			atf_tc_fail("semctl GETNCNT: %d", i);
    484  1.1  pgoyette 		if (i == 5)
    485  1.1  pgoyette 			break;
    486  1.1  pgoyette 	}
    487  1.1  pgoyette 
    488  1.1  pgoyette 	/*
    489  1.1  pgoyette 	 * Now set the thundering herd in motion by initializing the
    490  1.1  pgoyette 	 * semaphore to the value 1.
    491  1.1  pgoyette 	 */
    492  1.1  pgoyette 	sun.val = 1;
    493  1.1  pgoyette 	ATF_REQUIRE_MSG(semctl(sender_semid, 0, SETVAL, sun) != -1,
    494  1.1  pgoyette 	    "sender: semctl SETVAL to 1: %d", errno);
    495  1.1  pgoyette 
    496  1.1  pgoyette 	/*
    497  1.1  pgoyette 	 * Wait for all children to finish
    498  1.1  pgoyette 	 */
    499  1.6  christos 	while (child_count-- > 0) {
    500  1.6  christos 		wait_result = wait(&c_status);
    501  1.6  christos 		ATF_REQUIRE_MSG(wait_result != -1, "wait failed: %s",
    502  1.6  christos 		    strerror(errno));
    503  1.6  christos 		ATF_REQUIRE_MSG(WIFEXITED(c_status),
    504  1.6  christos 		    "child abnormal exit: %d (sig %d)",
    505  1.6  christos 		    c_status, WTERMSIG(c_status));
    506  1.6  christos 		ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d",
    507  1.6  christos 		    WEXITSTATUS(c_status));
    508  1.6  christos 
    509  1.6  christos 		sun.buf = &s_ds;
    510  1.6  christos 		ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
    511  1.6  christos 		    "semctl IPC_STAT: %d", errno);
    512  1.6  christos 
    513  1.6  christos 		print_semid_ds(&s_ds, 0600);
    514  1.1  pgoyette 	}
    515  1.1  pgoyette }
    516  1.1  pgoyette 
    517  1.2  pgoyette ATF_TC_CLEANUP(sem, tc)
    518  1.1  pgoyette {
    519  1.4      jmmv 	int sender_semid;
    520  1.1  pgoyette 
    521  1.1  pgoyette 	/*
    522  1.2  pgoyette 	 * Remove the semaphore if it exists
    523  1.1  pgoyette 	 */
    524  1.4      jmmv 	sender_semid = read_int("sender_semid");
    525  1.6  christos 	if (sender_semid == -1)
    526  1.6  christos 		return;
    527  1.6  christos 	if (semctl(sender_semid, 0, IPC_RMID) == -1)
    528  1.6  christos 		err(EXIT_FAILURE, "semctl IPC_RMID");
    529  1.1  pgoyette }
    530  1.1  pgoyette 
    531  1.1  pgoyette void
    532  1.5  pgoyette print_semid_ds(struct semid_ds *sp, mode_t mode)
    533  1.1  pgoyette {
    534  1.1  pgoyette 	uid_t uid = geteuid();
    535  1.1  pgoyette 	gid_t gid = getegid();
    536  1.1  pgoyette 
    537  1.1  pgoyette 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
    538  1.1  pgoyette 	    sp->sem_perm.uid, sp->sem_perm.gid,
    539  1.1  pgoyette 	    sp->sem_perm.cuid, sp->sem_perm.cgid,
    540  1.1  pgoyette 	    sp->sem_perm.mode & 0777);
    541  1.1  pgoyette 
    542  1.1  pgoyette 	printf("nsems %u\n", sp->sem_nsems);
    543  1.1  pgoyette 
    544  1.1  pgoyette 	printf("otime: %s", ctime(&sp->sem_otime));
    545  1.1  pgoyette 	printf("ctime: %s", ctime(&sp->sem_ctime));
    546  1.1  pgoyette 
    547  1.1  pgoyette 	/*
    548  1.1  pgoyette 	 * Sanity check a few things.
    549  1.1  pgoyette 	 */
    550  1.1  pgoyette 
    551  1.1  pgoyette 	ATF_REQUIRE_MSG(sp->sem_perm.uid == uid && sp->sem_perm.cuid == uid,
    552  1.1  pgoyette 	    "uid mismatch");
    553  1.1  pgoyette 
    554  1.1  pgoyette 	ATF_REQUIRE_MSG(sp->sem_perm.gid == gid && sp->sem_perm.cgid == gid,
    555  1.1  pgoyette 	    "gid mismatch");
    556  1.1  pgoyette 
    557  1.1  pgoyette 	ATF_REQUIRE_MSG((sp->sem_perm.mode & 0777) == mode,
    558  1.1  pgoyette 	    "mode mismatch %o != %o", (sp->sem_perm.mode & 0777), mode);
    559  1.1  pgoyette }
    560  1.1  pgoyette 
    561  1.1  pgoyette void
    562  1.5  pgoyette waiter(void)
    563  1.1  pgoyette {
    564  1.1  pgoyette 	struct sembuf s;
    565  1.1  pgoyette 	int semid;
    566  1.1  pgoyette 
    567  1.1  pgoyette 	if ((semid = semget(semkey, 1, 0)) == -1)
    568  1.6  christos 		err(EXIT_FAILURE, "waiter: semget");
    569  1.1  pgoyette 
    570  1.1  pgoyette 	/*
    571  1.1  pgoyette 	 * Attempt to acquire the semaphore.
    572  1.1  pgoyette 	 */
    573  1.1  pgoyette 	s.sem_num = 0;
    574  1.1  pgoyette 	s.sem_op = -1;
    575  1.1  pgoyette 	s.sem_flg = SEM_UNDO;
    576  1.1  pgoyette 
    577  1.1  pgoyette 	if (semop(semid, &s, 1) == -1)
    578  1.6  christos 		err(EXIT_FAILURE, "waiter: semop -1");
    579  1.1  pgoyette 
    580  1.1  pgoyette 	printf("WOO!  GOT THE SEMAPHORE!\n");
    581  1.6  christos 	usleep(10000);
    582  1.1  pgoyette 
    583  1.1  pgoyette 	/*
    584  1.1  pgoyette 	 * Release the semaphore and exit.
    585  1.1  pgoyette 	 */
    586  1.1  pgoyette 	s.sem_num = 0;
    587  1.1  pgoyette 	s.sem_op = 1;
    588  1.1  pgoyette 	s.sem_flg = SEM_UNDO;
    589  1.1  pgoyette 
    590  1.1  pgoyette 	if (semop(semid, &s, 1) == -1)
    591  1.6  christos 		err(EXIT_FAILURE, "waiter: semop +1");
    592  1.1  pgoyette 
    593  1.6  christos 	exit(EXIT_SUCCESS);
    594  1.1  pgoyette }
    595  1.1  pgoyette 
    596  1.1  pgoyette /*
    597  1.1  pgoyette  * Test the SVID-compatible Shared Memory facility.
    598  1.1  pgoyette  */
    599  1.1  pgoyette 
    600  1.2  pgoyette ATF_TC_WITH_CLEANUP(shm);
    601  1.1  pgoyette ATF_TC_HEAD(shm, tc)
    602  1.1  pgoyette {
    603  1.1  pgoyette 
    604  1.1  pgoyette 	atf_tc_set_md_var(tc, "timeout", "3");
    605  1.1  pgoyette 	atf_tc_set_md_var(tc, "descr", "Checks sysv shared memory");
    606  1.1  pgoyette }
    607  1.1  pgoyette 
    608  1.1  pgoyette ATF_TC_BODY(shm, tc)
    609  1.1  pgoyette {
    610  1.1  pgoyette 	struct sigaction sa;
    611  1.1  pgoyette 	struct shmid_ds s_ds;
    612  1.1  pgoyette 	char *shm_buf;
    613  1.4      jmmv 	int sender_shmid;
    614  1.1  pgoyette 	int c_status;
    615  1.6  christos 	pid_t wait_result;
    616  1.1  pgoyette 
    617  1.1  pgoyette 	/*
    618  1.1  pgoyette 	 * Install a SIGSYS handler so that we can exit gracefully if
    619  1.1  pgoyette 	 * System V Shared Memory support isn't in the kernel.
    620  1.1  pgoyette 	 */
    621  1.1  pgoyette 	did_sigsys = 0;
    622  1.1  pgoyette 	sa.sa_handler = sigsys_handler;
    623  1.1  pgoyette 	sigemptyset(&sa.sa_mask);
    624  1.1  pgoyette 	sa.sa_flags = 0;
    625  1.1  pgoyette 	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
    626  1.1  pgoyette 	    "sigaction SIGSYS: %d", errno);
    627  1.1  pgoyette 
    628  1.1  pgoyette 	pgsize = sysconf(_SC_PAGESIZE);
    629  1.1  pgoyette 
    630  1.2  pgoyette 	shmkey = get_ftok(4160);
    631  1.2  pgoyette 	ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed");
    632  1.1  pgoyette 
    633  1.1  pgoyette 	ATF_REQUIRE_MSG((sender_shmid = shmget(shmkey, pgsize,
    634  1.1  pgoyette 					       IPC_CREAT | 0640)) != -1,
    635  1.1  pgoyette 	    "shmget: %d", errno);
    636  1.4      jmmv 	write_int("sender_shmid", sender_shmid);
    637  1.1  pgoyette 
    638  1.1  pgoyette 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1,
    639  1.1  pgoyette 	    "shmctl IPC_STAT: %d", errno);
    640  1.1  pgoyette 
    641  1.1  pgoyette 	print_shmid_ds(&s_ds, 0640);
    642  1.1  pgoyette 
    643  1.1  pgoyette 	s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600;
    644  1.1  pgoyette 
    645  1.1  pgoyette 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_SET, &s_ds) != -1,
    646  1.1  pgoyette 	    "shmctl IPC_SET: %d", errno);
    647  1.1  pgoyette 
    648  1.1  pgoyette 	memset(&s_ds, 0, sizeof(s_ds));
    649  1.1  pgoyette 
    650  1.1  pgoyette 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1,
    651  1.1  pgoyette 	    "shmctl IPC_STAT: %d", errno);
    652  1.1  pgoyette 
    653  1.1  pgoyette 	ATF_REQUIRE_MSG((s_ds.shm_perm.mode & 0777) == 0600,
    654  1.1  pgoyette 	    "IPC_SET of mode didn't hold");
    655  1.1  pgoyette 
    656  1.1  pgoyette 	print_shmid_ds(&s_ds, 0600);
    657  1.1  pgoyette 
    658  1.1  pgoyette 	shm_buf = shmat(sender_shmid, NULL, 0);
    659  1.1  pgoyette 	ATF_REQUIRE_MSG(shm_buf != (void *) -1, "sender: shmat: %d", errno);
    660  1.1  pgoyette 
    661  1.1  pgoyette 	/*
    662  1.1  pgoyette 	 * Write the test pattern into the shared memory buffer.
    663  1.1  pgoyette 	 */
    664  1.1  pgoyette 	strcpy(shm_buf, m2_str);
    665  1.1  pgoyette 
    666  1.6  christos 	fflush(stdout);
    667  1.6  christos 
    668  1.1  pgoyette 	switch ((child_pid = fork())) {
    669  1.1  pgoyette 	case -1:
    670  1.1  pgoyette 		atf_tc_fail("fork: %d", errno);
    671  1.1  pgoyette 		return;
    672  1.1  pgoyette 
    673  1.1  pgoyette 	case 0:
    674  1.1  pgoyette 		sharer();
    675  1.1  pgoyette 		break;
    676  1.1  pgoyette 
    677  1.1  pgoyette 	default:
    678  1.1  pgoyette 		break;
    679  1.1  pgoyette 	}
    680  1.1  pgoyette 
    681  1.1  pgoyette 	/*
    682  1.1  pgoyette 	 * Wait for child to finish
    683  1.1  pgoyette 	 */
    684  1.6  christos 	wait_result = wait(&c_status);
    685  1.6  christos 	ATF_REQUIRE_EQ_MSG(wait_result, child_pid, "wait returned %d (%s)",
    686  1.6  christos 	    wait_result, wait_result == -1 ? strerror(errno) : "");
    687  1.6  christos 	ATF_REQUIRE_MSG(WIFEXITED(c_status), "child abnormal exit: %d (sig %d)",
    688  1.6  christos 	    c_status, WTERMSIG(c_status));
    689  1.6  christos 	ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d",
    690  1.6  christos 	    WEXITSTATUS(c_status));
    691  1.1  pgoyette 
    692  1.6  christos 	ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1,
    693  1.6  christos 	    "shmctl IPC_STAT: %d", errno);
    694  1.1  pgoyette 
    695  1.6  christos 	print_shmid_ds(&s_ds, 0600);
    696  1.1  pgoyette }
    697  1.1  pgoyette 
    698  1.2  pgoyette ATF_TC_CLEANUP(shm, tc)
    699  1.1  pgoyette {
    700  1.4      jmmv 	int sender_shmid;
    701  1.1  pgoyette 
    702  1.1  pgoyette 	/*
    703  1.2  pgoyette 	 * Remove the shared memory area if it exists.
    704  1.1  pgoyette 	 */
    705  1.4      jmmv 	sender_shmid = read_int("sender_shmid");
    706  1.6  christos 	if (sender_shmid == -1)
    707  1.6  christos 		return;
    708  1.6  christos 	if (shmctl(sender_shmid, IPC_RMID, NULL) == -1)
    709  1.6  christos 		err(EXIT_FAILURE, "shmctl IPC_RMID");
    710  1.1  pgoyette }
    711  1.1  pgoyette 
    712  1.1  pgoyette void
    713  1.5  pgoyette print_shmid_ds(struct shmid_ds *sp, mode_t mode)
    714  1.1  pgoyette {
    715  1.1  pgoyette 	uid_t uid = geteuid();
    716  1.1  pgoyette 	gid_t gid = getegid();
    717  1.1  pgoyette 
    718  1.1  pgoyette 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
    719  1.1  pgoyette 	    sp->shm_perm.uid, sp->shm_perm.gid,
    720  1.1  pgoyette 	    sp->shm_perm.cuid, sp->shm_perm.cgid,
    721  1.1  pgoyette 	    sp->shm_perm.mode & 0777);
    722  1.1  pgoyette 
    723  1.6  christos 	printf("segsz %ju, lpid %d, cpid %d, nattch %u\n",
    724  1.6  christos 	    (uintmax_t)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid,
    725  1.1  pgoyette 	    sp->shm_nattch);
    726  1.1  pgoyette 
    727  1.1  pgoyette 	printf("atime: %s", ctime(&sp->shm_atime));
    728  1.1  pgoyette 	printf("dtime: %s", ctime(&sp->shm_dtime));
    729  1.1  pgoyette 	printf("ctime: %s", ctime(&sp->shm_ctime));
    730  1.1  pgoyette 
    731  1.1  pgoyette 	/*
    732  1.1  pgoyette 	 * Sanity check a few things.
    733  1.1  pgoyette 	 */
    734  1.1  pgoyette 
    735  1.1  pgoyette 	ATF_REQUIRE_MSG(sp->shm_perm.uid == uid && sp->shm_perm.cuid == uid,
    736  1.1  pgoyette 	    "uid mismatch");
    737  1.1  pgoyette 
    738  1.1  pgoyette 	ATF_REQUIRE_MSG(sp->shm_perm.gid == gid && sp->shm_perm.cgid == gid,
    739  1.1  pgoyette 	    "gid mismatch");
    740  1.1  pgoyette 
    741  1.5  pgoyette 	ATF_REQUIRE_MSG((sp->shm_perm.mode & 0777) == mode,
    742  1.5  pgoyette 	    "mode mismatch %o != %o", sp->shm_perm.mode & 0777, mode);
    743  1.1  pgoyette }
    744  1.1  pgoyette 
    745  1.1  pgoyette void
    746  1.5  pgoyette sharer(void)
    747  1.1  pgoyette {
    748  1.1  pgoyette 	int shmid;
    749  1.1  pgoyette 	void *shm_buf;
    750  1.1  pgoyette 
    751  1.1  pgoyette 	shmid = shmget(shmkey, pgsize, 0);
    752  1.6  christos 	if (shmid == -1)
    753  1.6  christos 		err(EXIT_FAILURE, "receiver: shmget");
    754  1.1  pgoyette 
    755  1.1  pgoyette 	shm_buf = shmat(shmid, NULL, 0);
    756  1.6  christos 	if (shm_buf == (void *) -1)
    757  1.6  christos 		err(EXIT_FAILURE, "receiver: shmat");
    758  1.1  pgoyette 
    759  1.1  pgoyette 	printf("%s\n", (const char *)shm_buf);
    760  1.1  pgoyette 
    761  1.6  christos 	if (strcmp((const char *)shm_buf, m2_str) != 0)
    762  1.6  christos 		errx(EXIT_FAILURE, "receiver: data isn't correct");
    763  1.6  christos 
    764  1.6  christos 	exit(EXIT_SUCCESS);
    765  1.1  pgoyette }
    766  1.1  pgoyette 
    767  1.1  pgoyette ATF_TP_ADD_TCS(tp)
    768  1.1  pgoyette {
    769  1.1  pgoyette 
    770  1.1  pgoyette 	ATF_TP_ADD_TC(tp, msg);
    771  1.1  pgoyette 	ATF_TP_ADD_TC(tp, sem);
    772  1.1  pgoyette 	ATF_TP_ADD_TC(tp, shm);
    773  1.1  pgoyette 
    774  1.1  pgoyette 	return atf_no_error();
    775  1.1  pgoyette }
    776