/* ========================================================================== */
/* Operating system API */
/*
 * Include this as the first header in a C source file that should access the
 * operating system. A C++ source file must never include this header.
 */

#ifdef __cplusplus
#  error The POSIX.1-1990 API has no C++ binding!
#endif  /* __cplusplus */


/* ========================================================================== */
/* Configuration (must be 1st) */

#include "config.h"


/* ========================================================================== */
/* Tell system headers that they should be POSIX conformant (must be 2nd) */

#ifdef POSIX_H
   /* This must always be the first header that is included */
#  error Never include this header more than once!
#endif  /* POSIX_H */
#define POSIX_H  1

/*
 * CHeck twice before requesting another API, this can have many side effects.
 * It is obvious that older APIs lack support for some features, but newer APIs
 * also have features removed (because they where deprecated). In both cases we
 * must provide replacements for (different) missing features.
 *
 * See also: ../INSTALL.HP-UX
 */
#if CFG_USE_POSIX_API >= 200809
#  define _POSIX_C_SOURCE  200809L
#elif CFG_USE_POSIX_API == 200112
   /*
    * Attention:
    * At least POSIX.1g-2000 is required for IP6 option
    */
#  define _POSIX_C_SOURCE  200112L
#else  /* CFG_USE_POSIX_API */
   /*
    * Attention:
    * POSIX.1-1990 is not sufficient because we need the POSIX.1b-1993 Realtime
    * and POSIX.1c-1996 thread extensions
    */
#  define _POSIX_C_SOURCE  199506L
#endif  /* CFG_USE_POSIX_API */

#if CFG_USE_XSI
#  if CFG_USE_POSIX_API >= 200809
      /*
       * Attention:
       * The POSIX version must be not greater than 200809 if this value is 700:
       * https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_01_02
       */
#     define _XOPEN_SOURCE  700
#  elif CFG_USE_POSIX_API == 200112
      /*
       * Attention:
       * The POSIX version must be not greater than 200112 if this value is 600:
       * http://pubs.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_02.html#tag_02_02_01_02
       */
#     define _XOPEN_SOURCE  600
#  else  /* CFG_USE_POSIX_API */
      /*
       * Attention:
       * The POSIX version must be not greater than 199506 if this value is 500:
       * http://pubs.opengroup.org/onlinepubs/7908799/xns/compilation.html
       */
#     define _XOPEN_SOURCE  500
#  endif  /* CFG_USE_POSIX_API */
#endif  /* CFG_USE_XSI */

/*
 * This definition allows linking objects compiled for XNS and BSD sockets:
 * http://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/xopen_networking.7.html
 */
#if defined(__hpux) && CFG_USE_XSI
#  define _HPUX_ALT_XOPEN_SOCKET_API  1
#endif   /* defined(__hpux) && CFG_USE_XSI */

#include <sys/types.h>
#include <pthread.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <errno.h>
#include <unistd.h>


/* ========================================================================== */
/* POSIX.1b realtime support */

#include <time.h>

#define struct_posix_timespec  struct timespec

#define posix_nanosleep  nanosleep

#if CFG_USE_FSC
#  define posix_fsync  fsync
#else  /* CFG_USE_FSC */
int  posix_fsync(int);
#endif  /* CFG_USE_FSC */


/* ========================================================================== */
/* POSIX.1c thread support */

#define POSIX_PTHREAD_MUTEX_INITIALIZER  PTHREAD_MUTEX_INITIALIZER
#define POSIX_PTHREAD_COND_INITIALIZER  PTHREAD_COND_INITIALIZER
#define POSIX_PTHREAD_CANCEL_DISABLE  PTHREAD_CANCEL_DISABLE

#define posix_pthread_t  pthread_t
#define posix_pthread_mutex_t  pthread_mutex_t
#define posix_pthread_cond_t  pthread_cond_t

#define posix_pthread_create  pthread_create
#define posix_pthread_cancel  pthread_cancel
#define posix_pthread_setcancelstate  pthread_setcancelstate
#define posix_pthread_join  pthread_join
#define posix_pthread_self  pthread_self
#define posix_pthread_equal  pthread_equal
#define posix_pthread_sigmask  pthread_sigmask
#define posix_pthread_cleanup_push  pthread_cleanup_push
#define posix_pthread_cleanup_pop  pthread_cleanup_pop
#define posix_pthread_mutex_lock  pthread_mutex_lock
#define posix_pthread_mutex_trylock  pthread_mutex_trylock
#define posix_pthread_mutex_unlock  pthread_mutex_unlock
#define posix_pthread_cond_wait  pthread_cond_wait
#define posix_pthread_cond_signal  pthread_cond_signal


/* ========================================================================== */
/* POSIX.2 support */

#include <stdio.h>

#define posix_popen  popen
#define posix_pclose  pclose


/* ========================================================================== */
/* System limits */

#if CFG_HDR_INTTYPES_H
#  include <inttypes.h>
#endif  /* CFG_HDR_INTTYPES_H */

#define POSIX_INT_MAX  INT_MAX
#define POSIX_UINT_MAX  UINT_MAX
#define POSIX_LONG_MAX  LONG_MAX
#define POSIX_ULONG_MAX  ULONG_MAX
#define POSIX_SSIZE_MAX  SSIZE_MAX
#ifdef SIZE_MAX
#  define POSIX_SIZE_MAX  SIZE_MAX
#else  /* SIZE_MAX */
   /* Adding 1 may fail on machines that don't use 2's complement arithmetic */
#  define POSIX_SIZE_MAX  ((size_t) POSIX_SSIZE_MAX * (size_t) 2)
#endif  /* SIZE_MAX */


/* ========================================================================== */
/* Environment and return values */

/* Pointer to array with environment variables */
extern char**  environ;
#define posix_environ  environ

/* Standard return values for processes */
#define POSIX_EXIT_SUCCESS  EXIT_SUCCESS
#define POSIX_EXIT_FAILURE  EXIT_FAILURE


/* ========================================================================== */
/* System information */

#include <sys/utsname.h>

#define struct_posix_utsname  struct utsname

#define posix_uname  uname


/* ========================================================================== */
/* System errors */

#define POSIX_EACCES  EACCES
#define POSIX_EAGAIN  EAGAIN
#define POSIX_EBADF   EBADF
#define POSIX_ECONNREFUSED  ECONNREFUSED
#define POSIX_EEXIST  EEXIST
#define POSIX_EINTR  EINTR
#define POSIX_EINPROGRESS  EINPROGRESS
#define POSIX_EINVAL  EINVAL
#define POSIX_EIO  EIO
#define POSIX_ENOENT  ENOENT
#define POSIX_ENOMEM  ENOMEM
#define POSIX_ENOPROTOOPT  ENOPROTOOPT
#define POSIX_ENOSYS  ENOSYS
#define POSIX_ENOTSOCK  ENOTSOCK
#define POSIX_EOVERFLOW  EOVERFLOW

#define posix_errno  errno


/* ========================================================================== */
/* Signal handling */

#include <signal.h>

#define posix_sig_atomic_t  sig_atomic_t

#define struct_posix_sigaction  struct sigaction

#define POSIX_SIGHUP  SIGHUP
#define POSIX_SIGINT  SIGINT
#define POSIX_SIGPIPE  SIGPIPE
#define POSIX_SIGQUIT  SIGQUIT
#define POSIX_SIGTERM  SIGTERM

#define POSIX_SIG_DFL  SIG_DFL
#define POSIX_SIG_IGN  SIG_IGN

#define POSIX_SIG_BLOCK  SIG_BLOCK
#define POSIX_SIG_SETMASK  SIG_SETMASK

#define posix_sigset_t  sigset_t

#define posix_kill  kill
#define posix_sigemptyset  sigemptyset
#define posix_sigaddset  sigaddset
#define posix_sigaction  sigaction


/* ========================================================================== */
/* Process handling */

#include <sys/wait.h>

#define posix_pid_t  pid_t

#define POSIX_WIFEXITED  WIFEXITED
#define POSIX_WEXITSTATUS  WEXITSTATUS

#define POSIX_WNOHANG  WNOHANG

#define posix_fork  fork
#define posix_execl  execl
#define posix_execlp  execlp
#define posix_waitpid  waitpid
#define posix_getpid  getpid


/* ========================================================================== */
/* Time */

#define posix_time_t  time_t
#define struct_posix_tm  struct tm

#define posix_time  time

#define posix_gmtime_r  gmtime_r
#define posix_localtime_r  localtime_r

/* The %z conversion was included into POSIX.1 since Issue 6 */
#if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
#  define posix_strftime  strftime
#endif  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI */

#if CFG_USE_XSI
#  include <sys/time.h>

#  define posix_time_t  time_t
#  define posix_suseconds_t  suseconds_t
#  define struct_posix_timeval  struct timeval
#else  /* CFG_USE_XSI */
#  define posix_suseconds_t  long int

struct posix_timeval
{
  posix_time_t  tv_sec;
  posix_suseconds_t  tv_usec;
};

#  define struct_posix_timeval  struct posix_timeval
#endif  /* CFG_USE_XSI */


/* ========================================================================== */
/* Memory management */

#if CFG_USE_MEMDEBUG
void*  posix_malloc(size_t);
void*  posix_realloc(void*, size_t);
void  posix_free(void*);
#else  /* CFG_USE_MEMDEBUG */
#  define posix_malloc  malloc
#  define posix_realloc  realloc
#  define posix_free  free
#endif  /* CFG_USE_MEMDEBUG */


/* ========================================================================== */
/* Random numbers */

#if CFG_USE_XSI
#  define posix_srandom  srandom
#  define posix_random  random
#else  /* CFG_USE_XSI */
void  posix_srandom(unsigned int);
long int  posix_random(void);
#endif  /* CFG_USE_XSI */


/* ========================================================================== */
/* File & directory handling */

#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>

#define posix_off_t  off_t

#define POSIX_SEEK_SET  SEEK_SET

#define POSIX_FD_CLOEXEC  FD_CLOEXEC

#define POSIX_O_NONBLOCK  O_NONBLOCK
#define POSIX_O_CREAT  O_CREAT
#define POSIX_O_TRUNC  O_TRUNC
#define POSIX_O_RDONLY  O_RDONLY
#define POSIX_O_WRONLY  O_WRONLY
#define POSIX_O_RDWR  O_RDWR
#define POSIX_O_EXCL  O_EXCL

#define POSIX_S_IRWXU  S_IRWXU
#define POSIX_S_IRWXG  S_IRWXG
#define POSIX_S_IRWXO  S_IRWXO
#define POSIX_S_IRUSR  S_IRUSR
#define POSIX_S_IWUSR  S_IWUSR
#define POSIX_S_IXUSR  S_IXUSR

#define POSIX_F_GETFL  F_GETFL
#define POSIX_F_SETFL  F_SETFL
#define POSIX_F_WRLCK  F_WRLCK
#define POSIX_F_SETLK  F_SETLK
#define POSIX_F_SETFD  F_SETFD

#define POSIX_STDIN_FILENO  STDIN_FILENO
#define POSIX_STDOUT_FILENO  STDOUT_FILENO

#define POSIX_DIR  DIR

#define POSIX_S_ISREG  S_ISREG
#define POSIX_S_ISDIR  S_ISDIR

#define posix_mode_t  mode_t
#define struct_posix_flock  struct flock
#define struct_posix_stat  struct stat
#define struct_posix_dirent  struct dirent

#define posix_dup2  dup2
#define posix_pipe  pipe
#define posix_unlink  unlink
#define posix_rename  rename
#define posix_open  open
#define posix_fdopen  fdopen
#define posix_close  close
#define posix_lseek  lseek
#define posix_read  read
#define posix_write  write
#define posix_fcntl  fcntl
#define posix_fgetc  fgetc
#define posix_mkdir  mkdir
#define posix_rmdir  rmdir
#define posix_opendir  opendir
#define posix_readdir  readdir
#define posix_closedir  closedir
#define posix_stat  stat

#if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
#  define posix_ftruncate  ftruncate
#  define posix_lstat  lstat
#  define posix_symlink  symlink
#endif  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI */

/* Included into POSIX.1 since Issue 7 */
#if CFG_USE_POSIX_API >= 200809 || CFG_USE_XSI
#  define posix_mkstemp  mkstemp
#else  /* CFG_USE_POSIX_API >= 200809 || CFG_USE_XSI */
int  posix_mkstemp(char*);
#endif  /* CFG_USE_POSIX_API >= 200809 || CFG_USE_XSI */

#if CFG_USE_POSIX_API >= 200809
#  define  posix_scandir  scandir
#else  /* CFG_USE_POSIX_API >= 200809 */
int  posix_scandir(const char*, struct_posix_dirent***,
                   int (*sel)(struct_posix_dirent*),
                   int (*compar)(const struct_posix_dirent**,
                                 const struct_posix_dirent**));
#endif  /* CFG_USE_POSIX_API >= 200809 */


/* ========================================================================== */
/* System limits */

#  define POSIX_PC_NAME_MAX  _PC_NAME_MAX
#  define POSIX_PC_PATH_MAX  _PC_PATH_MAX

#  define posix_pathconf  pathconf


/* ========================================================================== */
/* NLS */

#if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
#  include <locale.h>

#  define POSIX_LC_ALL  LC_ALL
#  define POSIX_LC_CTYPE  LC_CTYPE
#  define POSIX_LC_MESSAGES  LC_MESSAGES

#  define posix_setlocale  setlocale
#endif  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI */

#if  CFG_USE_POSIX_API >= 200809 || CFG_USE_XSI
#  include <nl_types.h>
#  include <langinfo.h>

#  define POSIX_NL_MSGMAX  NL_MSGMAX
#  define POSIX_NL_CAT_LOCALE  NL_CAT_LOCALE

#  define posix_nl_catd  nl_catd

#  define posix_nl_langinfo  nl_langinfo
#  define posix_catopen  catopen
#  define posix_catgets  catgets
#  define posix_catclose  catclose
#endif  /*  CFG_USE_POSIX_API >= 200809 || CFG_USE_XSI */

/* These functions are part of POSIX.1 since Issue 7 */
#if  CFG_USE_POSIX_API >= 200809
#  include <strings.h>

#  define POSIX_LC_CTYPE_MASK  LC_CTYPE_MASK

#  define posix_locale_t  locale_t

#  define posix_newlocale  newlocale
#  define posix_freelocale  freelocale
#  define posix_strcasecmp_l  strcasecmp_l
#  define posix_strncasecmp_l  strncasecmp_l
#else  /*  CFG_USE_POSIX_API >= 200809 */
#  define POSIX_LC_CTYPE_MASK  0

typedef int  posix_locale_t;

posix_locale_t  posix_newlocale(int, const char*, posix_locale_t);
void posix_freelocale(posix_locale_t);
int  posix_strcasecmp_l(const char*, const char*, posix_locale_t);
int  posix_strncasecmp_l(const char*, const char*, size_t, posix_locale_t);
#endif  /* CFG_USE_POSIX_API >= 200809 */


/* ========================================================================== */
/* BSD socket interface (XNS) */

/*
 * If the system report the IP6 option as available, we expect that it provides
 * XNS too (logical OR)
 */
#if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI || CFG_USE_IP6
#  include <netinet/in.h>
#  include <arpa/inet.h>

#  define POSIX_AF_UNSPEC   AF_UNSPEC
#  define POSIX_AF_INET     AF_INET
#  if CFG_USE_IP6
#    define POSIX_AF_INET6  AF_INET6
#  endif   /* CFG_USE_IP6 */

#  define POSIX_MSG_PEEK  MSG_PEEK

#  define posix_ssize_t  ssize_t

/* Some systems that claim to be SUSv2 conformant don't define 'in_addr_t' */
#  if CFG_HDR_INTTYPES_H
#     include <inttypes.h>
typedef uint16_t  posix_in_port_t;
typedef uint32_t  posix_in_addr_t;
#  else  /* CFG_HDR_INTTYPES_H */
typedef CFG_UINT16_TYPE  posix_in_port_t;
typedef CFG_UINT32_TYPE  posix_in_addr_t;
#  endif  /* CFG_HDR_INTTYPES_H */

#  define struct_posix_in_addr  struct in_addr
#  define struct_posix_sockaddr_in  struct sockaddr_in

#  if CFG_USE_IP6
#     define struct_posix_in6_addr  struct in6_addr
#     define struct_posix_sockaddr_in6  struct sockaddr_in6
#  endif   /* CFG_USE_IP6 */

/* Bug in NetBSD: Declarations not exposed for POSIX.1-2001 without XSI */
#  define posix_htons  htons
#  define posix_htonl  htonl
#  define posix_ntohs  ntohs
#  define posix_ntohl  ntohl

#  define posix_inet_addr  inet_addr
#  if CFG_USE_POSIX_API >= 200112
#     define posix_inet_pton  inet_pton
#  else  /* CFG_USE_POSIX_API >= 200112 */
int  posix_inet_pton(int, const char*, void*);
#  endif  /* CFG_USE_POSIX_API >= 200112 */

#  include <sys/socket.h>

#  define posix_sa_family_t  sa_family_t
#  define posix_socklen_t  socklen_t

/*
 * 'struct sockaddr_storage' is broken on AIX (see documentation)
 * Currently there is no workaround provided by this module
 */
#  define struct_posix_sockaddr_storage  struct sockaddr_storage
#  define struct_posix_sockaddr  struct sockaddr

#  define  struct_posix_servent  struct servent
#  define  struct_posix_hostent  struct hostent

#  define  posix_getservbyname  getservbyname

#  if  CFG_USE_POSIX_API >= 200809
      /*
       * gethostbyname() is marked obsolete in POSIX.1 Issue 6
       * and was removed with Issue 7.
       * No replacement is implemented, use getaddrinfo() instead.
       */
#  else  /* CFG_USE_POSIX_API >= 200809 */
#     define  posix_gethostbyname  gethostbyname
#  endif  /* CFG_USE_POSIX_API >= 200809 */

#  define  posix_socket  socket

#  define POSIX_SOCK_STREAM  SOCK_STREAM

#  define  posix_connect  connect

#  define POSIX_SOL_SOCKET  SOL_SOCKET

#  define POSIX_SO_ERROR     SO_ERROR
#  define POSIX_SO_RCVTIMEO  SO_RCVTIMEO
#  define POSIX_SO_SNDTIMEO  SO_SNDTIMEO

#  define  posix_getsockopt  getsockopt
#  define  posix_setsockopt  setsockopt

#  define  posix_send  send
#  define  posix_recv  recv

#  include <poll.h>

#  define POSIX_POLLIN   POLLIN
#  define POSIX_POLLOUT  POLLOUT
#  define POSIX_POLLERR  POLLERR

#  define struct_posix_pollfd  struct pollfd

#  define  posix_poll  poll
#else  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI || CFG_USE_IP6 */
#  /* Use wrappers for original BSD socket API */
#  define BSD_FOR_POSIX
#  include "bsd.h"
#endif  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI || CFG_USE_IP6 */


/* ========================================================================== */
/* Address information */

#include <netdb.h>

/*
 * If the system report the IP6 option as available, we expect that it provides
 * the POSIX.1g API too (logical OR)
 *
 * Attention: This subsystem is emulated using 'gethostbyname()':
 * This function was marked obsolete by POSIX.1-2001 and was eventually removed
 * in POSIX.1-2008 => The emulation can no longer be used since POSIX.1-2008
 * (even for IPv4).
 */
#if CFG_USE_POSIX_API >= 200112 || CFG_USE_IP6
#  define POSIX_AI_ADDRCONFIG  AI_ADDRCONFIG

#  define POSIX_EAI_AGAIN     EAI_AGAIN
#  define POSIX_EAI_BADFLAGS  EAI_BADFLAGS
#  define POSIX_EAI_FAIL      EAI_FAIL
#  define POSIX_EAI_FAMILY    EAI_FAMILY
#  define POSIX_EAI_MEMORY    EAI_MEMORY
#  define POSIX_EAI_NONAME    EAI_NONAME
#  define POSIX_EAI_OVERFLOW  EAI_OVERFLOW
#  define POSIX_EAI_SERVICE   EAI_SERVICE
#  define POSIX_EAI_SOCKTYPE  EAI_SOCKTYPE
#  define POSIX_EAI_SYSTEM    EAI_SYSTEM

#  define struct_posix_addrinfo  struct addrinfo

#  define posix_freeaddrinfo  freeaddrinfo
#  define posix_getaddrinfo  getaddrinfo
#  define posix_gai_strerror  gai_strerror
#else  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_IP6 */
#  define POSIX_AI_ADDRCONFIG  0x0001

#  define POSIX_EAI_AGAIN     -1
#  define POSIX_EAI_BADFLAGS  -2
#  define POSIX_EAI_FAIL      -3
#  define POSIX_EAI_FAMILY    -4
#  define POSIX_EAI_MEMORY    -5
#  define POSIX_EAI_NONAME    -6
#  define POSIX_EAI_OVERFLOW  -7
#  define POSIX_EAI_SERVICE   -8
#  define POSIX_EAI_SOCKTYPE  -9
#  define POSIX_EAI_SYSTEM    -10

struct posix_addrinfo
{
   int  ai_flags;
   int  ai_family;
   int  ai_socktype;
   int  ai_protocol;
   posix_socklen_t  ai_addrlen;
   struct_posix_sockaddr*  ai_addr;
   char*  ai_canonname;
   struct posix_addrinfo*  ai_next;
};

#  define struct_posix_addrinfo  struct posix_addrinfo

void  posix_freeaddrinfo(struct_posix_addrinfo*);
int  posix_getaddrinfo(const char*, const char*, const struct_posix_addrinfo*,
                       struct_posix_addrinfo**);
const char*  posix_gai_strerror(int);
#endif  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_IP6 */


/* ========================================================================== */
/* Standard I/O */

#include <stdarg.h>
#include <string.h>
#include <stdio.h>

/*
 * Available since POSIX.1-2001.
 * Attention: The version in SUSv2 is not sufficient (different semantics)!
 */
#if CFG_USE_POSIX_API >= 200112
#  define posix_snprintf  snprintf
#else  /* CFG_USE_POSIX_API >= 200112 */
int  posix_snprintf(char*, size_t, const char*, ...);
#endif  /* CFG_USE_POSIX_API >= 200112 */

/* Part of POSIX.1 since Issue 7 */
#if CFG_USE_POSIX_API >= 200809
#  define posix_getline  getline
#else  /* CFG_USE_POSIX_API >= 200809 */
posix_ssize_t  posix_getline(char**, size_t*, FILE*);
#endif  /* CFG_USE_POSIX_API >= 200809 */


/* ========================================================================== */
/* Regular expression matching */

#if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI || CFG_USE_CLB
#  include <regex.h>

#  define POSIX_REG_EXTENDED  REG_EXTENDED
#  define POSIX_REG_ICASE     REG_ICASE
#  define POSIX_REG_NOSUB     REG_NOSUB
#  define POSIX_REG_NEWLINE   REG_NEWLINE

#  define posix_regex_t  regex_t

#  define posix_regcomp  regcomp
#  define posix_regerror  regerror
#  define posix_regexec  regexec
#  define posix_regfree  regfree
#endif  /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI || CFG_USE_CLB */


/* EOF */
