/* Test shm, sem and fork.  */
#include "config.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>

int *shm;

#ifndef HAVE_SEMUN
union semun {
  int val;
  struct semid_ds *buf;
  ushort *array;
};
#endif
  
#define SHM_KEY 0x1234567
#define SEM_KEY 0x2345678
int
main (void)
{
  int shmid;
  int semid;
  struct sembuf sops;
  union semun semun;
  int val;
  int pid;
  int res;

  semun.val = 0;

  /* Create the shm.  */
  shmid = shmget (SHM_KEY, 2 * sizeof (int), IPC_CREAT | IPC_EXCL | 0666);
  if (shmid == -1)
    {
      shmid = shmget (SHM_KEY, 2 * sizeof (int), 0666);
      if (shmid == -1)
	abort ();
      printf ("shm was already created, id is %d\n", shmid);
    }

  /* Create a semaphore.  */
  semid = semget (SEM_KEY, 1, IPC_CREAT | 0666);
  if (semid == -1)
    {
      perror ("server semget");
      exit (1);
    }

  pid = fork ();

  /* Attach memory.  */
  shm = shmat (shmid, 0, 0);
  if (shm == (void *)-1)
    {
      perror ("shmat");
      exit (1);
    }
  printf ("Attach at %p\n", shm);

  if (pid)
    shm[0] = shm[1] = 1;

  /* Get a semaphore.  */
  if (pid)
    {
      semun.val = 1;
      if (semctl (semid, 0, SETVAL, semun) == -1)
	{
	  perror ("semctl");
	  exit (1);
	}
    }
      
  /* Get a sem.  */
  sops.sem_num = 0;
  sops.sem_op = -1;
  sops.sem_flg = 0;
  if (semop (semid, &sops, 1) == -1)
    {
      perror ("semop");
      exit (1);
    }
  if (pid == 0)
    {
      shm[0] *= 2;
      shm[1] *= 2;
    }
  else
    {
      shm[0] += 1;
      shm[1] += 1;
    }
  printf ("Val id now (%d, %d)\n", shm[0], shm[1]);
  sops.sem_num = 0;
  sops.sem_op = 1;
  sops.sem_flg = 0;
  if (semop (semid, &sops, 1) == -1)
    {
      perror ("semop");
      exit (1);
    }

  if (pid == 0)
    exit (0);

  if (pid)
    {
      if (wait (&res) != pid)
	perror ("wait");
      if (semctl (semid, 1, IPC_RMID, semun) == -1)
	perror ("semop IPC_RMID");
      if (shmctl (shmid, IPC_RMID, 0) == -1)
	perror ("shmctl IPC_RMID");
    }
  return 0;
}
