NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: standards/58275: tentative fix



The following reply was made to PR standards/58275; it has been noted by GNATS.

From: Guilherme Janczak <guilherme.janczak%yandex.com@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: standards/58275: tentative fix
Date: Fri, 24 May 2024 19:34:47 +0000

 I'm working on a fix. It's incomplete and I haven't tested it at all, so 
 it's certainly not ready for merge, but before going further, I'd like a 
 NetBSD developer's opinion.
 
 The idea of this diff follows the gist of my suggested fix, learn from 
 FreeBSD and OpenBSD's solutions.
 
 We define __$standard_VISIBLE internal use macros corresponding to 
 NetBSD, X/Open, POSIX, and C which are set according to the feature test 
 macros defined by the user, making sure that broader standards imply 
 narrower ones:
 
 If the user defines _NETBSD_SOURCE, __NBSD_VISIBLE is defined
 internally. If __NBSD_VISIBLE is defined, the latest __XOPEN_VISIBLE is 
 implied. If __XOPEN_VISIBLE is defined, it implies a respective 
 __POSIX_VISIBLE value. If __POSIX_VISIBLE is defined, it implies a
 respective __ISO_C_VISIBLE value. 
 
 Likewise, Defining a narrower feature test macro such as 
 _POSIX_C_SOURCE will define appropriate __POSIX_VISIBLE
 and __ISO_C_VISIBLE values.
 
 This means that headers only need to check for the narrowest standard
 that defines a symbol, unless a a narrower standard adopts a function 
 from a broader standard, then you need to check if either is the 
 appropriate version. The rest is implicit. Edge cases like functions
 removed from standards but kept in NetBSD are easy to handle, simply
 check if either the appropriate standard visibility is within a certain
 range or __NBSD_VISIBLE is defined. Conflicts between NetBSD and
 standards are checked by looking at which standard feature test macros
 the user defined explicitly. Here are some examples:
 
 setegid() was added in POSIX-2001. There is no need to check for 
 __XOPEN_VISIBLE or __NETBSD_VISIBLE here because they imply appropriate 
 __POSIX_VISIBLE values:
 #if __POSIX_VISIBLE >= 200112
 int	 setegid(gid_t);
 #endif
 
 symlink() was added in XPGv4.2 and adopted as part of the POSIX base 
 standard in POSIX-2001. We need to check for both __XOPEN_VISIBLE and 
 __POSIX_VISIBLE here because the function was initially added by X/Open, 
 and later made mandatory in POSIX:
 #if __XOPEN_VISIBLE >= 420 || __POSIX_VISIBLE >= 200112
 int	 symlink(const char *, const char *);
 #endif
 
 gethostid() was added in XPGv4.2 and remains part of the XSI option in
 POSIX. We only check for __XOPEN_VISIBLE, we don't need to check for
 __NETBSD_VISIBLE because it implies the latest __XOPEN_VISIBLE:
 #if __XOPEN_VISIBLE >= 420
 long	 gethostid(void);
 #endif
 
 ualarm() was added in XPG4.2, became part of the XSI option from POSIX
 in POSIX-2001, and was removed from POSIX in POSIX-2008. NetBSD retains
 it:
 #if __XOPEN_VISIBLE >= 420 && __XOPEN_VISIBLE < 700 || defined(__NBSD_VISIBLE)
 useconds_t ualarm(useconds_t, useconds_t);
 #endif
 
 NetBSD contains standard and nonstandard versions of lchown().
 We first check if the function should be visible. Then we peek into the
 standard feature test macros to see why they're visible, and pick
 between the standard or NetBSD standard version as appropriate:
 +#if __XOPEN_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809
 #if defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE)
 int	 lchown(const char *, uid_t, gid_t) __RENAME(__posix_lchown);
 #else
 int	 lchown(const char *, uid_t, gid_t);
 #endif
 
 This diff already fixes a LOT of bugs as is. Many, many functions aren't 
 visible when they should, or are visible when they shouldn't. The 
 comment explaining standard feature test macros in sys/sys/featuretest.h 
 contained incorrect information. There are lots of other inconsequential
 changes, for instance, I commented the code that figures out which
 standards to make available with links to free and legal online copies
 of the standards; some of the visibility bugs suggest the developers
 relied on 2nd sourced information or haven't read the standards (finding
 them can definitely be hard and some weren't originally available for 
 free), so those links are vital.
 
 I think it's evident this new approach is a lot simpler and less error
 prone than the current one. It should also be less lines of code once
 more headers are migrated to the new approach.
 
 I'd like to ask if this design needs any changes and if there's any bug
 for bug compatibility I need to keep. For instance, I already noticed
 NetBSD lacks a standards-compliant version of setpgrp(), using the 
 NetBSD version isn't even binary compatible with the standard one:
 NetBSD: int setpgrp(pid_t, pid_t);
 POSIX: pid_t setpgrp(void);
 NetBSD declares its nonstandard version where a standard one should be,
 I made it so it's only declared if _NETBSD_SOURCE is defined by the
 user.
 
 If i get the go ahead I'll figure out how to test this (I guess
 compiling all of NetBSD's base is a good start?) and try to get the
 processs started with just unistd.h and featuretest.h, other headers to
 follow later so maybe other people can have a hand at it too, I'm not 
 sure if I even have the skills to do this for all headers.
 
 
 Index: include/unistd.h
 ===================================================================
 RCS file: /cvsroot/src/include/unistd.h,v
 retrieving revision 1.164
 diff -u -p -u -p -r1.164 unistd.h
 --- include/unistd.h	19 Jan 2024 18:40:35 -0000	1.164
 +++ include/unistd.h	24 May 2024 17:48:42 -0000
 @@ -1,4 +1,4 @@
 -/*	$NetBSD: unistd.h,v 1.164 2024/01/19 18:40:35 christos Exp $	*/
 +/*	$NetBSD: unistd.h,v 1.166 2024/05/20 01:30:33 christos Exp $	*/
  
  /*-
   * Copyright (c) 1998, 1999, 2008 The NetBSD Foundation, Inc.
 @@ -81,25 +81,175 @@
  #define	STDOUT_FILENO	1	/* standard output file descriptor */
  #define	STDERR_FILENO	2	/* standard error file descriptor */
  
 +#define F_ULOCK		0
 +#define F_LOCK		1
 +#define F_TLOCK		2
 +#define F_TEST		3
 +
  #include <sys/null.h>
  
  __BEGIN_DECLS
 +
 +#if __POSIX_VISIBLE >= 200809
 +int	linkat(int, const char *, int, const char *, int);
 +int	renameat(int, const char *, int, const char *);
 +int	faccessat(int, const char *, int, int);
 +int	fchownat(int, const char *, uid_t, gid_t, int);
 +ssize_t	readlinkat(int, const char *, char *, size_t);
 +int	symlinkat(const char *, int, const char *);
 +int	unlinkat(int, const char *, int);
 +int	fexecve(int, char * const *, char * const *);
 +#endif
 +
 +#if __POSIX_VISIBLE >= 200112
 +int	 setegid(gid_t);
 +int	 seteuid(uid_t);
 +
 +#  ifndef _BSD_INTPTR_T_
 +#  define _BSD_INTPTR_T_
 +typedef __intptr_t      intptr_t;
 +#  endif
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 520
 +int	 gethostname(char *, size_t);
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 500 || __POSIX_VISIBLE >= 200809L
 +ssize_t	 pread(int, void *, size_t, off_t);
 +ssize_t	 pwrite(int, const void *, size_t, off_t);
 +#endif
 +
 +#if __POSIX_VISIBLE >= 199506
 +int	 getlogin_r(char *, size_t);
 +int	 ttyname_r(int, char *, size_t);
 +int	 fdatasync(int);
 +
 +#  ifndef __PTHREAD_ATFORK_DECLARED
 +#  define __PTHREAD_ATFORK_DECLARED
 +int	 pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
 +#  endif
 +#endif /* __POSIX_VISIBLE >= 199506 */
 +
 +#if __XOPEN_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809
 +pid_t	 getsid(pid_t);
 +int	 fchdir(int);
 +pid_t	 getpgid(pid_t);
 +#  if defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE)
 +int	 lchown(const char *, uid_t, gid_t) __RENAME(__posix_lchown);
 +#  else
 +int	 lchown(const char *, uid_t, gid_t);
 +#  endif
 +#endif
 +
 +
 +#if __XOPEN_VISIBLE >= 420 || __POSIX_VISIBLE >= 200112
 +int	 symlink(const char *, const char *);
 +void	 sync(void);
 +
 +#  if defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE)
 +int	 fchown(int, uid_t, gid_t) __RENAME(__posix_fchown);
 +#  else
 +int	 fchown(int, uid_t, gid_t);
 +#  endif
 +
 +#  if __SSP_FORTIFY_LEVEL == 0
 +ssize_t	 readlink(const char * __restrict, char * __restrict, size_t);
 +#  endif
 +#endif /* __XOPEN_VISIBLE >= 420 || __POSIX_VISIBLE >= 200112 */
 +
 +#if __XOPEN_VISIBLE >= 420
 +long	 gethostid(void);
 +int	 lockf(int, int, off_t);
 +int	 setregid(gid_t, gid_t);
 +int	 setreuid(uid_t, uid_t);
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 420 && __XOPEN_VISIBLE < 700 || defined(__NBSD_VISIBLE)
 +useconds_t ualarm(useconds_t, useconds_t);
 +int	 usleep(useconds_t);
 +
 +#  ifndef __LIBC12_SOURCE__
 +pid_t	 vfork(void) __RENAME(__vfork14) __returns_twice;
 +#  endif
 +#  ifndef __AUDIT__
 +char	*getwd(char *);				/* obsoleted by getcwd() */
 +#  endif
 +#endif /* __XOPEN_VISIBLE >= 420 && __XOPEN_VISIBLE < 700 || __NBSD_VISIBLE */
 +
 +/*
 + * The following three syscalls are also defined in <sys/types.h>
 + * We protect them against double declarations.
 + */
 +#ifndef __OFF_T_SYSCALLS_DECLARED
 +#define __OFF_T_SYSCALLS_DECLARED
 +off_t	 lseek(int, off_t, int);
 +int	 truncate(const char *, off_t);
 +
 +#  if __XOPEN_VISIBLE >= 420 || __POSIX_VISIBLE >= 199309
 +int	 ftruncate(int, off_t);
 +#  endif
 +#endif /* !defined(__OFF_T_SYSCALLS_DECLARED) */
 +
 +#if __POSIX_VISIBLE >= 199200
 +size_t	 confstr(int, char *, size_t);
 +#endif
 +
 +#if __POSIX_VISIBLE >= 199012 && __POSIX_VISIBLE < 200112 || \
 +    defined(__NBSD_VISIBLE)
 +#  ifndef __CUSERID_DECLARED
 +#  define __CUSERID_DECLARED
 +/* also declared in stdio.h */
 +char	*cuserid(char *);
 +#  endif
 +#endif
 +
 +#if __POSIX_VISIBLE >= 199012 && \
 +    (defined(_POSIX_C_SOURCE) || defined(_POSIX_SOURCE) || \
 +     defined(_XOPEN_SOURCE))
 +int	chown(const char *, uid_t, gid_t) __RENAME(__posix_chown);
 +#else
 +int	chown(const char *, uid_t, gid_t);
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 300 || __POSIX_VISIBLE >= 199309
 +int	 fsync(int);
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 420 && __XOPEN_VISIBLE < 600 || defined(__NBSD_VISIBLE)
 +int	 brk(void *);
 +int	 getdtablesize(void);
 +void	*sbrk(intptr_t);
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 100
 +int	 nice(int);
 +__aconst char *crypt(const char *, const char *);
 +int	 encrypt(char *, int);
 +void	 swab(const void * __restrict, void * __restrict, ssize_t);
 +#endif
 +
 +#if __XOPEN_VISIBLE >= 100 && __XOPEN_VISIBLE < 600 || defined(__NBSD_VISIBLE)
 +int	 chroot(const char *);
 +char	*getpass(const char *);
 +#endif
 +
 +#if __SSP_FORTIFY_LEVEL == 0
 +char	*getcwd(char *, size_t);
 +ssize_t	 read(int, void *, size_t);
 +#endif
 +
 +/* POSIX 1990 or 1988 functions below. */
 +
 +int	 getopt(int, char * const [], const char *);
 +extern	 char *optarg;			/* getopt(3) external variables */
 +extern	 int opterr, optind, optopt;
 +
  __dead	 void _exit(int);
  int	 access(const char *, int);
  unsigned int alarm(unsigned int);
  int	 chdir(const char *);
 -#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
 -int	chown(const char *, uid_t, gid_t) __RENAME(__posix_chown);
 -#else
 -int	chown(const char *, uid_t, gid_t);
 -#endif /* defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) */
  int	 close(int);
 -size_t	 confstr(int, char *, size_t);
 -#ifndef __CUSERID_DECLARED
 -#define __CUSERID_DECLARED
 -/* also declared in stdio.h */
 -char	*cuserid(char *);	/* obsolete */
 -#endif /* __CUSERID_DECLARED */
  int	 dup(int);
  int	 dup2(int, int);
  int	 execl(const char *, const char *, ...) __null_sentinel;
 @@ -110,15 +260,11 @@ int	 execve(const char *, char * const *
  int	 execvp(const char *, char * const *);
  pid_t	 fork(void);
  long	 fpathconf(int, int);
 -#if __SSP_FORTIFY_LEVEL == 0
 -char	*getcwd(char *, size_t);
 -#endif
  gid_t	 getegid(void);
  uid_t	 geteuid(void);
  gid_t	 getgid(void);
  int	 getgroups(int, gid_t []);
  __aconst char *getlogin(void);
 -int	 getlogin_r(char *, size_t);
  pid_t	 getpgrp(void);
  pid_t	 getpid(void);
  pid_t	 getppid(void);
 @@ -128,9 +274,6 @@ int	 link(const char *, const char *);
  long	 pathconf(const char *, int);
  int	 pause(void);
  int	 pipe(int *);
 -#if __SSP_FORTIFY_LEVEL == 0
 -ssize_t	 read(int, void *, size_t);
 -#endif
  int	 rmdir(const char *);
  int	 setgid(gid_t);
  int	 setpgid(pid_t, pid_t);
 @@ -144,192 +287,18 @@ __aconst char *ttyname(int);
  int	 unlink(const char *);
  ssize_t	 write(int, const void *, size_t);
  
 -
 -/*
 - * IEEE Std 1003.2-92, adopted in X/Open Portability Guide Issue 4 and later
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 2 || defined(_XOPEN_SOURCE) || \
 -    defined(_NETBSD_SOURCE)
 -int	 getopt(int, char * const [], const char *);
 -
 -extern	 char *optarg;			/* getopt(3) external variables */
 -extern	 int opterr;
 -extern	 int optind;
 -extern	 int optopt;
 -#endif
 -
 -/*
 - * The Open Group Base Specifications, Issue 5; IEEE Std 1003.1-2001 (POSIX)
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 200112L || (_XOPEN_SOURCE - 0) >= 500 || \
 -    defined(_NETBSD_SOURCE)
 -#if __SSP_FORTIFY_LEVEL == 0
 -ssize_t	 readlink(const char * __restrict, char * __restrict, size_t);
 -#endif
 -#endif
 -
 -/*
 - * The Open Group Base Specifications, Issue 6; IEEE Std 1003.1-2001 (POSIX)
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 200112L || (_XOPEN_SOURCE - 0) >= 600 || \
 -    defined(_NETBSD_SOURCE)
 -int	 setegid(gid_t);
 -int	 seteuid(uid_t);
 -#endif
 -
 -/*
 - * The following three syscalls are also defined in <sys/types.h>
 - * We protect them against double declarations.
 - */
 -#ifndef __OFF_T_SYSCALLS_DECLARED
 -#define __OFF_T_SYSCALLS_DECLARED
 -off_t	 lseek(int, off_t, int);
 -int	 truncate(const char *, off_t);
 -/*
 - * IEEE Std 1003.1b-93,
 - * also found in X/Open Portability Guide >= Issue 4 Version 2
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 199309L || \
 -    (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
 -    (_XOPEN_SOURCE - 0) >= 500 || defined(_NETBSD_SOURCE)
 -int	 ftruncate(int, off_t);
 -#endif
 -#endif /* __OFF_T_SYSCALLS_DECLARED */
 -
 -
 -/*
 - * IEEE Std 1003.1b-93, adopted in X/Open CAE Specification Issue 5 Version 2
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
 -    defined(_NETBSD_SOURCE)
 -int	 fdatasync(int);
 -int	 fsync(int);
 -#endif
 -
 -
 -/*
 - * IEEE Std 1003.1c-95, also adopted by X/Open CAE Spec Issue 5 Version 2
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 199506L || (_XOPEN_SOURCE - 0) >= 500 || \
 -    defined(_REENTRANT) || defined(_NETBSD_SOURCE)
 -int	 ttyname_r(int, char *, size_t);
 -#ifndef __PTHREAD_ATFORK_DECLARED
 -#define __PTHREAD_ATFORK_DECLARED
 -int	 pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
 -#endif
 -#endif
 -
 -/*
 - * X/Open Portability Guide, all issues
 - */
 -#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
 -int	 chroot(const char *);
 -int	 nice(int);
 -#endif
 -
 -
 -/*
 - * X/Open Portability Guide >= Issue 4
 - */
 -#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
 -__aconst char *crypt(const char *, const char *);
 -int	 encrypt(char *, int);
 -char	*getpass(const char *);
 -#endif
 -#if defined(_XOPEN_SOURCE) || (_POSIX_C_SOURCE - 0) >= 200809L || \
 -    defined(_NETBSD_SOURCE)
 -pid_t	 getsid(pid_t);
 -#endif
 -
 -
 -/*
 - * X/Open Portability Guide >= Issue 4 Version 2
 - */
 -#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
 -    (_XOPEN_SOURCE - 0) >= 500 || defined(_NETBSD_SOURCE)
 -#ifndef _BSD_INTPTR_T_
 -typedef __intptr_t      intptr_t;
 -#define _BSD_INTPTR_T_
 -#endif
 -
 -#define F_ULOCK		0
 -#define F_LOCK		1
 -#define F_TLOCK		2
 -#define F_TEST		3
 -
 -int	 brk(void *);
 -int	 fchdir(int);
 -#if defined(_XOPEN_SOURCE)
 -int	 fchown(int, uid_t, gid_t) __RENAME(__posix_fchown);
 -#else
 -int	 fchown(int, uid_t, gid_t);
 -#endif
 -int	 getdtablesize(void);
 -long	 gethostid(void);
 -int	 gethostname(char *, size_t);
 -__pure int
 -	 getpagesize(void);		/* legacy */
 -pid_t	 getpgid(pid_t);
 -#if defined(_XOPEN_SOURCE)
 -int	 lchown(const char *, uid_t, gid_t) __RENAME(__posix_lchown);
 -#else
 -int	 lchown(const char *, uid_t, gid_t);
 -#endif
 -int	 lockf(int, int, off_t);
 -void	*sbrk(intptr_t);
 -/* XXX prototype wrong! */
 -int	 setpgrp(pid_t, pid_t);			/* obsoleted by setpgid() */
 -int	 setregid(gid_t, gid_t);
 -int	 setreuid(uid_t, uid_t);
 -void	 swab(const void * __restrict, void * __restrict, ssize_t);
 -int	 symlink(const char *, const char *);
 -void	 sync(void);
 -useconds_t ualarm(useconds_t, useconds_t);
 -int	 usleep(useconds_t);
 -#ifndef __LIBC12_SOURCE__
 -pid_t	 vfork(void) __RENAME(__vfork14) __returns_twice;
 -#endif
 -
 -#ifndef __AUDIT__
 -char	*getwd(char *);				/* obsoleted by getcwd() */
 -#endif
 -#endif /* _XOPEN_SOURCE_EXTENDED || _XOPEN_SOURCE >= 500 || _NETBSD_SOURCE */
 -
 -
 -/*
 - * X/Open CAE Specification Issue 5 Version 2
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 200112L || (_XOPEN_SOURCE - 0) >= 500 || \
 -    defined(_NETBSD_SOURCE)
 -ssize_t	 pread(int, void *, size_t, off_t);
 -ssize_t	 pwrite(int, const void *, size_t, off_t);
 -#endif /* (_POSIX_C_SOURCE - 0) >= 200112L || ... */
 -
 -/*
 - * X/Open Extended API set 2 (a.k.a. C063)
 - */
 -#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0 >= 700) || \
 -    defined(_NETBSD_SOURCE)
 -int	linkat(int, const char *, int, const char *, int);
 -int	renameat(int, const char *, int, const char *);
 -int	faccessat(int, const char *, int, int);
 -int	fchownat(int, const char *, uid_t, gid_t, int);
 -ssize_t	readlinkat(int, const char *, char *, size_t);
 -int	symlinkat(const char *, int, const char *);
 -int	unlinkat(int, const char *, int);
 -int	fexecve(int, char * const *, char * const *);
 -#endif
 -
 -
  /*
   * Implementation-defined extensions
   */
 -#if defined(_NETBSD_SOURCE)
 +#ifdef __NBSD_VISIBLE
 +int	 setpgrp(pid_t, pid_t);			/* obsoleted by setpgid() */
  int	 acct(const char *);
  int	 closefrom(int);
  int	 des_cipher(const char *, char *, long, int);
  int	 des_setkey(const char *);
 -int	 dup3(int, int, int);
 +#ifndef __LIBC12_SOURCE__
 +int	 dup3(int, int, int) __RENAME(__dup3100);
 +#endif
  void	 endusershell(void);
  int	 exect(const char *, char * const *, char * const *);
  int	 execvpe(const char *, char * const *, char * const *);
 @@ -412,7 +381,7 @@ extern const char *const *sys_siglist __
  #endif /* __SYS_SIGLIST_DECLARED */
  extern	 int optreset;		/* getopt(3) external variable */
  extern	 char *suboptarg;	/* getsubopt(3) external variable */
 -#endif
 +#endif /* defined(__NBSD_VISIBLE) */
  
  #ifdef _LIBC_INTERNAL
  pid_t	__fork(void);
 @@ -420,4 +389,5 @@ pid_t	__locked_fork(int *) __weak;
  #endif
  
  __END_DECLS
 +
  #endif /* !_UNISTD_H_ */
 Index: sys/sys/featuretest.h
 ===================================================================
 RCS file: /cvsroot/src/sys/sys/featuretest.h,v
 retrieving revision 1.10
 diff -u -p -u -p -r1.10 featuretest.h
 --- sys/sys/featuretest.h	26 Apr 2013 18:29:06 -0000	1.10
 +++ sys/sys/featuretest.h	24 May 2024 17:49:05 -0000
 @@ -4,12 +4,32 @@
   * Written by Klaus Klein <kleink%NetBSD.org@localhost>, February 2, 1998.
   * Public domain.
   *
 - * NOTE: Do not protect this header against multiple inclusion.  Doing
 + * NOTE: Do not protect these definitions against multiple inclusion.  Doing
   * so can have subtle side-effects due to header file inclusion order
   * and testing of e.g. _POSIX_SOURCE vs. _POSIX_C_SOURCE.  Instead,
   * protect each CPP macro that we want to supply.
 + *
 + * The definitions which aren't currently protected by header guards are being
 + * phased out. Don't add any new unprotected code, and do not try to protect the
 + * unprotected code.
   */
  
 +#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE)
 +#define _POSIX_C_SOURCE 1L
 +#endif
 +
 +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) && \
 +    !defined(_XOPEN_SOURCE) && !defined(_NETBSD_SOURCE)
 +#define _NETBSD_SOURCE 1
 +#endif
 +
 +#if ((_POSIX_C_SOURCE - 0) >= 199506L || (_XOPEN_SOURCE - 0) >= 500) && \
 +    !defined(_REENTRANT)
 +#define _REENTRANT
 +#endif
 +
 +#ifndef _SYS_FEATURETEST_H_
 +#define _SYS_FEATURETEST_H_
  /*
   * Feature-test macros are defined by several standards, and allow an
   * application to specify what symbols they want the system headers to
 @@ -18,36 +38,36 @@
   * specify complete standards, and if one of these is defined, header
   * files will try to conform to the relevant standard.  They are:
   *
 - * ANSI macros:
 - * _ANSI_SOURCE			ANSI C89
 - *
 - * POSIX macros:
 - * _POSIX_SOURCE == 1		IEEE Std 1003.1 (version?)
 - * _POSIX_C_SOURCE == 1		IEEE Std 1003.1-1990
 - * _POSIX_C_SOURCE == 2		IEEE Std 1003.2-1992
 - * _POSIX_C_SOURCE == 199309L	IEEE Std 1003.1b-1993
 - * _POSIX_C_SOURCE == 199506L	ISO/IEC 9945-1:1996
 - * _POSIX_C_SOURCE == 200112L	IEEE Std 1003.1-2001
 - * _POSIX_C_SOURCE == 200809L   IEEE Std 1003.1-2008
 + * NetBSD macros:
 + * _NETBSD_SOURCE == 1		Declare all NetBSD symbols except strtonum().
 + * _OPENBSD_SOURCE == 1		Declare strtonum().
 + * _ANSI_SOURCE			Declare only ANSI C89 symbols.
   *
   * X/Open macros:
 - * _XOPEN_SOURCE		System Interfaces and Headers, Issue 4, Ver 2
 - * _XOPEN_SOURCE_EXTENDED == 1	XSH4.2 UNIX extensions
 - * _XOPEN_SOURCE == 500		System Interfaces and Headers, Issue 5
 - * _XOPEN_SOURCE == 520		Networking Services (XNS), Issue 5.2
 - * _XOPEN_SOURCE == 600		IEEE Std 1003.1-2001, XSI option
   * _XOPEN_SOURCE == 700		IEEE Std 1003.1-2008, XSI option
 + * _XOPEN_SOURCE == 600		IEEE Std 1003.1-2001, XSI option
 + * _XOPEN_SOURCE == 520		Networking Services (XNS), Issue 5.2 Draft 2.0
 + * _XOPEN_SOURCE == 500		System Interfaces and Headers Issue 5
 + * _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1
 + *				System Interfaces and Headers Issue 4, Ver 2
 + * _XOPEN_SOURCE		System Interfaces and Headers Issue 4
   *
 - * NetBSD macros:
 - * _NETBSD_SOURCE == 1		Make all NetBSD features available.
 + * POSIX macros:
 + * _POSIX_C_SOURCE == 200809L	IEEE Std 1003.1-2008
 + * _POSIX_C_SOURCE == 200112L	IEEE Std 1003.1-2001
 + * _POSIX_C_SOURCE == 199506L	ISO/IEC 9945-1:1996
 + * _POSIX_C_SOURCE == 199309L	IEEE Std 1003.1b-1993
 + * _POSIX_C_SOURCE == 2		IEEE Std 1003.2-1992
 + * _POSIX_C_SOURCE == 1		IEEE Std 1003.1-1992 without new 1992 interfaces
 + * _POSIX_SOURCE   == 1		IEEE Std 1003.1-1990, IEEE Std 1003.1-1988
   *
 - * If more than one of these "major" feature-test macros is defined,
 - * then the set of facilities provided (and namespace used) is the
 - * union of that specified by the relevant standards, and in case of
 - * conflict, the earlier standard in the above list has precedence (so
 - * if both _POSIX_C_SOURCE and _NETBSD_SOURCE are defined, the version
 - * of rename() that's used is the POSIX one).  If none of the "major"
 - * feature-test macros is defined, _NETBSD_SOURCE is assumed.
 + * If more than one of these "major" feature-test macros is defined, then the
 + * set of facilities provided (and namespace used) is the union of that
 + * specified by the relevant standards, and in case of conflict, X/Open and
 + * POSIX have precedence over NetBSD (so if both _POSIX_C_SOURCE and
 + * _NETBSD_SOURCE are defined, the version of rename() that's used is the POSIX
 + * one).  If none of the "major" feature-test macros is defined, _NETBSD_SOURCE
 + * is assumed.
   *
   * There are also "minor" feature-test macros, which enable extra
   * functionality in addition to some base standard.  They should be
 @@ -61,16 +81,129 @@
   *		<http://ftp.sas.com/standards/large.file/x_open.20Mar96.html>
   */
  
 -#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE)
 -#define _POSIX_C_SOURCE	1L
 +#if defined(__NBSD_VISIBLE)  || defined(__XOPEN_VISIBLE) || \
 +    defined(__POSIX_VISIBLE) || defined(__ISO_C_VISIBLE)
 +#error "__*_VISIBLE aren't feature test macros. Use NetBSD or standard macros."
  #endif
  
 -#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) && \
 -    !defined(_XOPEN_SOURCE) && !defined(_NETBSD_SOURCE)
 -#define _NETBSD_SOURCE 1
 +#if (!defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE) && \
 +    !defined(_POSIX_SOURCE) && !defined(_ANSI_SOURCE)) || \
 +    defined(_NETBSD_SOURCE)
 +#  define __NBSD_VISIBLE
  #endif
  
 -#if ((_POSIX_C_SOURCE - 0) >= 199506L || (_XOPEN_SOURCE - 0) >= 500) && \
 -    !defined(_REENTRANT)
 -#define _REENTRANT
 +#ifdef __NBSD_VISIBLE
 +#  define __XOPEN_VISIBLE 700
  #endif
 +
 +#ifdef _XOPEN_SOURCE
 +/*
 + * The Open Group Base Specifications Issue 7, 2018 edition
 + * https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/
 + */
 +#  if _XOPEN_SOURCE - 0 >= 700
 +#    define __XOPEN_VISIBLE 700
 +/*
 + * The Open Group Base Specifications Issue 6
 + * https://pubs.opengroup.org/onlinepubs/009695399/
 + */
 +#  elif _XOPEN_SOURCE - 0 >= 600
 +#    define __XOPEN_VISIBLE 600
 +/*
 + * Networking Services (XNS), Issue 5.2 Draft 2.0:
 + * https://pubs.opengroup.org/onlinepubs/009619199/
 + */
 +#  elif _XOPEN_SOURCE - 0 >= 520
 +#    define __XOPEN_VISIBLE 520
 +/*
 + * System Interfaces and Headers Issue 5
 + * https://pubs.opengroup.org/onlinepubs/009639399/toc.pdf
 + *
 + * Web conversions of this standard lack markings like EX (extension), don't
 + * read web coversions.
 + */
 +#  elif _XOPEN_SOURCE - 0 >= 500
 +#    define __XOPEN_VISIBLE 500
 +/*
 + * System Interfaces and Headers Issue 4, Version 2
 + * https://pubs.opengroup.org/onlinepubs/9695969499/toc.pdf
 + */
 +#  elif _XOPEN_SOURCE_EXTENDED - 0 == 1
 +#    define __XOPEN_VISIBLE 420
 +/*
 + * I can't get my hands on XPG older than XPGv4.2. However, XPGv4.2 explains
 + * _XOPEN_SOURCE_EXTENDED was added in XPGv4.2 and _XOPEN_SOURCE was added in
 + * XPGv4.0, so it appears there is no feature test macro for older versions, and
 + * we provide no way to request an older standard.
 + */
 +#  else
 +#    define __XOPEN_VISIBLE 400
 +#  endif
 +#endif
 +
 +#if defined(_POSIX_C_SOURCE) || defined(__XOPEN_VISIBLE)
 +#  if _POSIX_C_SOURCE - 0   >= 200809L || __XOPEN_VISIBLE >= 700
 +#    define __POSIX_VISIBLE 200809
 +#  elif _POSIX_C_SOURCE - 0 >= 200112L || __XOPEN_VISIBLE >= 600
 +#    define __POSIX_VISIBLE 200112
 +/* POSIX.1c: Threads extensions (IEEE Std 1003.1c-1995) */
 +#  elif _POSIX_C_SOURCE - 0 >= 199506L || __XOPEN_VISIBLE >= 500
 +#    define __POSIX_VISIBLE 199506
 +/* POSIX.1b: Real-time extensions (IEEE Std 1003.1b-1993) */
 +#  elif _POSIX_C_SOURCE - 0 >= 199309L
 +#    define __POSIX_VISIBLE 199309
 +/*
 + * POSIX.2: Shell and Utilities (IEEE Std 1003.2-1992)
 + *
 + * IEEE P1003.2 Draft 11.2:
 + * https://mirror.math.princeton.edu/pub/oldlinux/Linux.old/Ref-docs/POSIX/all.pdf
 + * XXX: Careful, the link is a draft. Figure out if any organization bought the
 + * right to publish the final standard for free.
 + */
 +#  elif _POSIX_C_SOURCE - 0 >= 2      || __XOPEN_VISIBLE >= 400
 +#    define __POSIX_VISIBLE 199200
 +#  elif _POSIX_C_SOURCE - 0 == 1
 +/*
 + * POSIX 1990 doesn't define _POSIX_C_SOURCE. However, 1992 states that if
 + * _POSIX_C_SOURCE == 1, that is the same as defining _POSIX_SOURCE.
 + */
 +#    define __POSIX_VISIBLE 199012
 +#  endif
 +#endif
 +
 +#ifdef _POSIX_SOURCE
 +/*
 + * NIST adopted these, we can have them for free.
 + * IEEE Std 1003.1, 1990:
 + * https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub151-2.pdf
 + * IEEE Std 1003.1, 1988:
 + * https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub151-1.pdf
 + *
 + * There doesn't seem to be a way to differentiate between 1990 and 1988, so we
 + * assume 1990.
 + */
 +#  define __POSIX_VISIBLE 199012
 +#endif
 +
 +#if defined(_ISOC11_SOURCE) || defined(__NBSD_VISIBLE)
 +#  define __ISO_C_VISIBLE 2011
 +#elif defined(_ISOC99_SOURCE) || __POSIX_VISIBLE >= 200112
 +#  define __ISO_C_VISIBLE 1999
 +#else
 +#  define __ISO_C_VISIBLE 1990
 +#endif
 +
 +/* Otherwise, define the visibilities of standards with an invalid value so we
 + * can check with `__VISIBLE >= 1` instead of the uglier `__VISIBLE - 0 >= 1`
 + */
 +#ifndef __XOPEN_VISIBLE
 +#  define __XOPEN_VISIBLE -1
 +#endif
 +#ifndef __POSIX_VISIBLE
 +#  define __POSIX_VISIBLE -1
 +#endif
 +#ifndef __ISO_C_VISIBLE
 +#  define __ISO_C_VISIBLE -1
 +#endif
 +
 +#endif /* defined(_SYS_FEATURETEST_H_) */
 



Home | Main Index | Thread Index | Old Index