File:  [DragonFly] / src / tools / regression / sysvshm / shmtest.c
Revision 1.1: download - view: text, annotated - select for diffs
Sat Oct 18 12:13:01 2003 UTC (11 years ago) by hmp
Branches: MAIN
CVS tags: HEAD
Add SysV IPC regression suite.

Obtained from:	NetBSD

    1: /*-
    2:  * Copyright (c) 1999 The NetBSD Foundation, Inc.
    3:  * All rights reserved.
    4:  *
    5:  * This code is derived from software contributed to The NetBSD Foundation
    6:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    7:  * NASA Ames Research Center.
    8:  *
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. All advertising materials mentioning features or use of this software
   18:  *    must display the following acknowledgement:
   19:  *	This product includes software developed by the NetBSD
   20:  *	Foundation, Inc. and its contributors.
   21:  * 4. Neither the name of The NetBSD Foundation nor the names of its
   22:  *    contributors may be used to endorse or promote products derived
   23:  *    from this software without specific prior written permission.
   24:  *
   25:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   26:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35:  * POSSIBILITY OF SUCH DAMAGE.
   36:  *
   37:  * Obtained from: $NetBSD: shmtest.c,v 1.3 2002/07/20 08:36:26 grant Exp $
   38:  * $DragonFly: src/tools/regression/sysvshm/shmtest.c,v 1.1 2003/10/18 12:13:01 hmp Exp $
   39:  */
   40: 
   41: /*
   42:  * Test the SVID-compatible Shared Memory facility.
   43:  */
   44: 
   45: #include <sys/param.h>
   46: #include <sys/ipc.h>
   47: #include <sys/shm.h>
   48: #include <sys/wait.h>
   49: 
   50: #include <err.h>
   51: #include <errno.h>
   52: #include <signal.h>
   53: #include <stdio.h>
   54: #include <stdlib.h>
   55: #include <string.h>
   56: #include <time.h>
   57: #include <unistd.h>
   58: 
   59: int	main __P((int, char *[]));
   60: void	print_shmid_ds __P((struct shmid_ds *, mode_t));
   61: void	sigsys_handler __P((int));
   62: void	sigchld_handler __P((int));
   63: void	cleanup __P((void));
   64: void	receiver __P((void));
   65: void	usage __P((void));
   66: 
   67: const char *m_str = "The quick brown fox jumped over the lazy dog.";
   68: 
   69: int	sender_shmid = -1;
   70: pid_t	child_pid;
   71: 
   72: key_t	shmkey;
   73: 
   74: size_t	pgsize;
   75: 
   76: int
   77: main(argc, argv)
   78: 	int argc;
   79: 	char *argv[];
   80: {
   81: 	struct sigaction sa;
   82: 	struct shmid_ds s_ds;
   83: 	sigset_t sigmask;
   84: 	char *shm_buf;
   85: 
   86: 	if (argc != 2)
   87: 		usage();
   88: 
   89: 	/*
   90: 	 * Install a SIGSYS handler so that we can exit gracefully if
   91: 	 * System V Shared Memory support isn't in the kernel.
   92: 	 */
   93: 	sa.sa_handler = sigsys_handler;
   94: 	sigemptyset(&sa.sa_mask);
   95: 	sa.sa_flags = 0;
   96: 	if (sigaction(SIGSYS, &sa, NULL) == -1)
   97: 		err(1, "sigaction SIGSYS");
   98: 
   99: 	/*
  100: 	 * Install and SIGCHLD handler to deal with all possible exit
  101: 	 * conditions of the receiver.
  102: 	 */
  103: 	sa.sa_handler = sigchld_handler;
  104: 	sigemptyset(&sa.sa_mask);
  105: 	sa.sa_flags = 0;
  106: 	if (sigaction(SIGCHLD, &sa, NULL) == -1)
  107: 		err(1, "sigaction SIGCHLD");
  108: 
  109: 	pgsize = sysconf(_SC_PAGESIZE);
  110: 
  111: 	shmkey = ftok(argv[1], 4160);
  112: 
  113: 	/*
  114: 	 * Initialize child_pid to ourselves to that the cleanup function
  115: 	 * works before we create the receiver.
  116: 	 */
  117: 	child_pid = getpid();
  118: 
  119: 	/*
  120: 	 * Make sure that when the sender exits, the message queue is
  121: 	 * removed.
  122: 	 */
  123: 	if (atexit(cleanup) == -1)
  124: 		err(1, "atexit");
  125: 
  126: 	if ((sender_shmid = shmget(shmkey, pgsize, IPC_CREAT | 0640)) == -1)
  127: 		err(1, "shmget");
  128: 
  129: 	if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1)
  130: 		err(1, "shmctl IPC_STAT");
  131: 
  132: 	print_shmid_ds(&s_ds, 0640);
  133: 
  134: 	s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600;
  135: 
  136: 	if (shmctl(sender_shmid, IPC_SET, &s_ds) == -1)
  137: 		err(1, "shmctl IPC_SET");
  138: 
  139: 	memset(&s_ds, 0, sizeof(s_ds));
  140: 
  141: 	if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1)
  142: 		err(1, "shmctl IPC_STAT");
  143: 
  144: 	if ((s_ds.shm_perm.mode & 0777) != 0600)
  145: 		err(1, "IPC_SET of mode didn't hold");
  146: 
  147: 	print_shmid_ds(&s_ds, 0600);
  148: 
  149: 	if ((shm_buf = shmat(sender_shmid, NULL, 0)) == (void *) -1)
  150: 		err(1, "sender: shmat");
  151: 
  152: 	/*
  153: 	 * Write the test pattern into the shared memory buffer.
  154: 	 */
  155: 	strcpy(shm_buf, m_str);
  156: 
  157: 	switch ((child_pid = fork())) {
  158: 	case -1:
  159: 		err(1, "fork");
  160: 		/* NOTREACHED */
  161: 
  162: 	case 0:
  163: 		receiver();
  164: 		break;
  165: 
  166: 	default:
  167: 		break;
  168: 	}
  169: 
  170: 	/*
  171: 	 * Suspend forever; when we get SIGCHLD, the handler will exit.
  172: 	 */
  173: 	sigemptyset(&sigmask);
  174: 	(void) sigsuspend(&sigmask);
  175: 
  176: 	/*
  177: 	 * ...and any other signal is an unexpected error.
  178: 	 */
  179: 	errx(1, "sender: received unexpected signal");
  180: }
  181: 
  182: void
  183: sigsys_handler(signo)
  184: 	int signo;
  185: {
  186: 
  187: 	errx(1, "System V Shared Memory support is not present in the kernel");
  188: }
  189: 
  190: void
  191: sigchld_handler(signo)
  192: 	int signo;
  193: {
  194: 	struct shmid_ds s_ds;
  195: 	int cstatus;
  196: 
  197: 	/*
  198: 	 * Reap the child; if it exited successfully, then the test passed!
  199: 	 */
  200: 	if (waitpid(child_pid, &cstatus, 0) != child_pid)
  201: 		err(1, "waitpid");
  202: 
  203: 	if (WIFEXITED(cstatus) == 0)
  204: 		errx(1, "receiver exited abnormally");
  205: 
  206: 	if (WEXITSTATUS(cstatus) != 0)
  207: 		errx(1, "receiver exited with status %d",
  208: 		    WEXITSTATUS(cstatus));
  209: 
  210: 	/*
  211: 	 * If we get here, the child has exited normally, and thus
  212: 	 * we should exit normally too.  First, tho, we print out
  213: 	 * the final stats for the message queue.
  214: 	 */
  215: 
  216: 	if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1)
  217: 		err(1, "shmctl IPC_STAT");
  218: 
  219: 	print_shmid_ds(&s_ds, 0600);
  220: 
  221: 	exit(0);
  222: }
  223: 
  224: void
  225: cleanup()
  226: {
  227: 
  228: 	/*
  229: 	 * If we're the sender, and it exists, remove the shared memory area.
  230: 	 */
  231: 	if (child_pid != 0 && sender_shmid != -1) {
  232: 		if (shmctl(sender_shmid, IPC_RMID, NULL) == -1)
  233: 			warn("shmctl IPC_RMID");
  234: 	}
  235: }
  236: 
  237: void
  238: print_shmid_ds(sp, mode)
  239: 	struct shmid_ds *sp;
  240: 	mode_t mode;
  241: {
  242: 	uid_t uid = geteuid();
  243: 	gid_t gid = getegid();
  244: 
  245: 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
  246: 	    sp->shm_perm.uid, sp->shm_perm.gid,
  247: 	    sp->shm_perm.cuid, sp->shm_perm.cgid,
  248: 	    sp->shm_perm.mode & 0777);
  249: 
  250: 	printf("segsz %lu, lpid %d, cpid %d, nattch %u\n",
  251: 	    (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid,
  252: 	    sp->shm_nattch);
  253: 
  254: 	printf("atime: %s", ctime(&sp->shm_atime));
  255: 	printf("dtime: %s", ctime(&sp->shm_dtime));
  256: 	printf("ctime: %s", ctime(&sp->shm_ctime));
  257: 
  258: 	/*
  259: 	 * Sanity check a few things.
  260: 	 */
  261: 
  262: 	if (sp->shm_perm.uid != uid || sp->shm_perm.cuid != uid)
  263: 		errx(1, "uid mismatch");
  264: 
  265: 	if (sp->shm_perm.gid != gid || sp->shm_perm.cgid != gid)
  266: 		errx(1, "gid mismatch");
  267: 
  268: 	if ((sp->shm_perm.mode & 0777) != mode)
  269: 		errx(1, "mode mismatch");
  270: }
  271: 
  272: void
  273: usage()
  274: {
  275: 
  276: 	fprintf(stderr, "usage: %s keypath\n", getprogname());
  277: 	exit(1);
  278: }
  279: 
  280: void
  281: receiver()
  282: {
  283: 	int shmid;
  284: 	void *shm_buf;
  285: 
  286: 	if ((shmid = shmget(shmkey, pgsize, 0)) == -1)
  287: 		err(1, "receiver: shmget");
  288: 
  289: 	if ((shm_buf = shmat(shmid, NULL, 0)) == (void *) -1)
  290: 		err(1, "receiver: shmat");
  291: 
  292: 	printf("%s\n", (const char *)shm_buf);
  293: 	if (strcmp((const char *)shm_buf, m_str) != 0)
  294: 		err(1, "receiver: data isn't correct");
  295: 
  296: 	exit(0);
  297: }