#include "available-stubs.h"

#include <errno.h>
#include <sys/shm.h>
#include "machine.h"
#include "checker_api.h"
#include "message.h"

#ifdef HAVE_shmctl
/* From `/usr/include/sys/shm.h:11'.  */
int chkr_stub_shmctl (int shmid, int cmd, struct shmid_ds *buf)
     __asm__ (CHKR_PREFIX ("shmctl"));
int
chkr_stub_shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
  switch (cmd)
    {
    case IPC_STAT:
      stubs_chkr_check_addr (buf, sizeof (struct shmid_ds), CHKR_TW, "buf");
      break;
    case SHM_UNLOCK:
    case SHM_LOCK:
      break;
    case IPC_SET:
    case IPC_RMID:
      break;
    default:
      chkr_header (M_IPC_UNIMPLEMENT);
      chkr_printf (M_SEND_DESCRIPTION);
      return 1;		/* means error */
    }
  return shmctl (shmid, cmd,buf);
}
#endif /* HAVE_shmctl */

#ifdef HAVE_shmget
/* From `/usr/include/sys/shm.h:12'.  */
int chkr_stub_shmget (key_t key, int size, int flag) __asm__ (CHKR_PREFIX ("shmget"));
int
chkr_stub_shmget (key_t key, int size, int flag)
{
#if USE_BI_JUMP
  __builtin_jump (shmget);
#else
  return shmget (key, size, flag);
#endif /* !USE_BI_JUMP */
}
#endif /* HAVE_shmget */

#ifdef HAVE_shmat
/* From `/usr/include/sys/shm.h:13'.  */
char * chkr_stub_shmat (int shmid, char *shmaddr, int flags)
     __asm__ (CHKR_PREFIX ("shmat"));
char *
chkr_stub_shmat (int shmid, char *shmaddr, int flags)
{
  char *res;

  if (shmaddr >= (char *)MM_LOW && shmaddr <= (char *)MM_HIGH)
    {
      errno = EINVAL;
      return (char *)-1;
    }

  res = shmat (shmid, shmaddr, flags);

  if (res != -1)
    chkr_new_segshm (shmid, res, flags);
  return res;
}
#endif /* HAVE_shmat */

#ifdef HAVE_shmdt
/* From `/usr/include/sys/shm.h:14'.  */
int chkr_stub_shmdt (char *shmaddr) __asm__ (CHKR_PREFIX ("shmdt"));
int
chkr_stub_shmdt (char *shmaddr)
{
  int res;

  res = shmdt (shmaddr);
  if (res == 0)
    remove_shm (shmaddr);
  return res;
}
#endif /* HAVE_shmdt */

