Requesting GNU extensions but otherwise POSIX-conformant functions? - c

Is there a way with feature test macros to have glibc expose GNU extensions (functions not specified in POSIX, and additional flag/argument macros for standard functions, like MAP_ANONYMOUS), but still prefer POSIX semantics whenever the POSIX and GNU definitions conflict? I'm thinking things like basename, strerror_r, etc.

For the specific case of basename(), including <libgen.h> header gives you the XPG / POSIX definition.
MAP_ANONYMOUS isn't a GNU extension (_GNU_SOURCE), it's defined if either _BSD_SOURCE or _SVID_SOURCE is defined.

Related

Why do Windows and Linux have different strdup implementations: strdup() and _strdup()?

When working with strdup on Windows I found out that _strdup is Windows specific, but when I ran the same code on Linux it required strdup without the underscore. Does anyone know the history behind this difference, as-well as some information on how you have dealt with this problem when writing cross-platform code?
There are several functions that are part of the POSIX specification, i.e. Linux and most other UNIX variants, that are not part of standard C. These include strdup, write, read, and others.
The reasoning for the leading underscore is as follows, taken from the MSDN docs:
The Universal C Run-Time Library (UCRT) supports most of the C
standard library required for C++ conformance. It implements the C99
(ISO/IEC 9899:1999) library, with certain exceptions: The type-generic
macros defined in , and strict type compatibility in
. The UCRT also implements a large subset of the POSIX.1
(ISO/IEC 9945-1:1996, the POSIX System Application Program Interface)
C library. However, it's not fully conformant to any specific POSIX
standard. The UCRT also implements several Microsoft-specific
functions and macros that aren't part of a standard.
Functions specific to the Microsoft implementation of Visual C++ are
found in the vcruntime library. Many of these functions are for
internal use and can't be called by user code. Some are documented for
use in debugging and implementation compatibility.
The C++ standard reserves names that begin with an underscore in the
global namespace to the implementation. Both the POSIX functions and
Microsoft-specific runtime library functions are in the global
namespace, but aren't part of the standard C runtime library. That's
why the preferred Microsoft implementations of these functions have a
leading underscore. For portability, the UCRT also supports the
default names, but the Microsoft C++ compiler issues a deprecation
warning when code that uses them is compiled. Only the default names
are deprecated, not the functions themselves. To suppress the warning,
define _CRT_NONSTDC_NO_WARNINGS before including any headers in code
that uses the original POSIX names.
I've handled that by having a #define that check if the program is being compiled for Windows, and if so create another #define to map the POSIX name to the Windows specific name. There are a few choices you can check, although probably the most reliable is _MSC_VER which is defined if MSVC is the compiler.
#ifdef _MSC_VER
#define strdup(p) _strdup(p)
#endif

Warning: implicit declaration of function only when using -std=c99

I have a program that uses the <stdio.h> function dprintf. If I complie this without -std=c99 I have no problems, however if I try to compile wih this flag I'll get the "implicit function declaration" warning
Does this mean that dprintf is not declared in <stdio.h> for c99? If so, where is the function declaration?
dprintf is not in C99. It's only in recent versions of POSIX.
You can compile with -std=gnu99 to include both C99 and POSIX functions (plus some extensions).
dprintf is a Posix function, making it an extension to standard C.
Posix (and other) extension functions need to be enabled by defining an appropriate feature test macro before including any standard header. On Linux , at least, you'll find the appropriate feature test macro listed in the manpage, right after the prototype. For example, man dprintf tells you:
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
dprintf(), vdprintf():
Since glibc 2.10:
_POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
_GNU_SOURCE
That means that, assuming that you are using a not too ancient glibc version, your file should start:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
Although you can achieve the same effect on gcc by using non-standard -std options, using feature test macros correctly makes your code portable between different Posix implementations.

Macros like _GNU_SOURCE, what do they mean?

Lot many times while referring to linux header files or man files, I see the following macros used..
Ex : man mkstemp
In this man page we can see that the below macros are featured.
_GNU_SOURCE
_BSD_SOURCE
_SVID_SOURCE
_XOPEN_SOURCE
_XOPEN_SOURCE_EXTENDED
What am I supposed to understand to write a correct program if I am using these API's/Headers?
Read feature_test_macros(7) man page (and the §1.3.4 Feature Test Macros chapter of GNU libc documentation).
You might compile your whole program with some special feature symbols. For instance, I often compile a program with -D_GNU_SOURCE. This means that I want all the extra GNU specific features provided on my system by GNU libc etc. You could instead compile with -D_POSIX_C_SOURCE=200112L if you want strict POSIX 2001 compliance (and nothing more).
Alternatively, if all your .c files are just #include-ing only your own header, that header could start with #define _GNU_SOURCE 1 followed by several system #include ....
The point is that a GNU/Linux system obey to several standards (with GNU providing its own standard), and you might choose which ones.
GNU libc (which is the most common libc available on Linux, but you could use some other libc, like musl-libc ....) provides a lot of functions, features and headers not available on other systems, e.g. <argp.h> (header), fopencookie (function), %m format control directive in printf feature.
It is also relevant if you intend to code a program portable to other POSIX systems (e.g. to MacOSX). On MacOSX or AIX systems you don't have getopt_long since it is a GNU specific function.

c89 and POSIX at the same time

Is it possible to use POSIX functions even in strict std=c89? When I try to compile executable on Linux in strict ANSI C mode, both gcc and clang know nothing about functions like readlink or realpath, though headers are included. Since I have to use POSIX functions even in ANSI C mode, I'm looking for way to do it. I've thought about dlsym, but I don't know which library I'll have to open. Such calls are surrounded with #ifdef's, so they won't rise an alarm on the other system. Cross-platform solution needed. Thanks in advance!
You're looking for "feature-test macros". See the Single Unix Specification, Issue 6: System Interfaces Chapter 2.2, "The Compilation Environment"
Edit:
To quote that page:
The _POSIX_C_SOURCE Feature Test Macro
A POSIX-conforming application should ensure that the feature test macro
_POSIX_C_SOURCE is defined before inclusion of any header.
GCC and clang currently define _POSIX_C_SOURCE for you by default unless one of c89, c99, c11, or any behaviorally equivalent string is passed to the compiler's -std option.
Additionally:
The _XOPEN_SOURCE Feature Test Macro
An XSI-conforming application should ensure that the feature test macro
_XOPEN_SOURCE is defined with the value 600 before inclusion of any header.
This is needed to enable the functionality described in The _POSIX_C_SOURCE
Feature Test Macro and in addition to enable the XSI extension.
In other words, to guarantee your program (a.k.a. application) can use POSIX, either #define _POSIX_C_SOURCE 200112L before any header is included or pass the -D_POSIX_C_SOURCE=200112L option to the compiler. For the XSI functionality, you must define _XOPEN_SOURCE to a value of 600.
There is also a newer version of the Single Unix Specification — Issue 7. Very similar text can be found in Issue 7. The only real differences with respect to the text above are the numbers for _POSIX_C_SOURCE and _XOPEN_SOURCE have been changed.
At least when a combination of gcc and glibc on linux, you can turn on non standard functions (e.g. those defined by posix) with #define's , see man feature_test_macros
e.g. #define _POSIX_C_SOURCE 200809L before including any header files, or by adding it to the compiler arguments:
gcc -std=c99 -D_POSIX_C_SOURCE=200809L ...

sigaction System Call

I was looking at the man page of sigaction, and I ended up looking at the following line.
sigaction(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
What do _POSIX_X_SOURCE, _X_OPEN_SOURCE, _POSIX_SOURCE mean? What to do with it?
These are feature test macros. Their purpose is to allow your program to inform the system header files which standards you want it to attempt to conform to, and what extensions you want available.
Without any feature test macros defined, implementations vary a lot in what macros, functions, and type definitions they make visible in their headers. A common practice is to make everything visible by default, which is a problem because "everything" is not very specific, and it's very possible that symbol names used in your program might clash with some of the extensions. Even if they don't clash now, there's no way to know if they will in the future. So the standards (like ISO C and POSIX) put strict requirements on the implementation that it not pollute the applications namespace with names not explicitly defined or reserved in the standards. When you use a feature test macro to request a particular standard, you're asking the implementation to ensure that (1) it provides everything defined in this standard, (2) it doesn't pollute your application's namespace by providing anything not defined in that standard.
A correct program should always explicitly use the right feature test macros for the standard(s) it's written to. The easiest way to do this is putting the right -D argument on the compiler command line (CFLAGS). Adding the #define as the first line in each source file also works. Be aware if you do it in source files though:
The feature test macros must be defined at the top before any system header is included.
It's usually a bad idea to use different feature test macros in different translation units.
As an aside, it's not exactly the same as the other feature test macros, but all modern programs should define _FILE_OFFSET_BITS=64 when built on Linux/glibc to request that off_t be 64-bit for large file support.
Here is a man for Feature macros: http://www.kernel.org/doc/man-pages/online/pages/man7/feature_test_macros.7.html
They will turn on or off some level of standard support in the headers.
E.g. _POSIX_C_SOURCE >= 1 means that POSIX.2-1992 or later should be supported; _X_OPEN_SOURCE means POSIX.1, POSIX.2, and XPG4 are enabled; and for greater values of macro (>=500; >=600; >=700) it will also turn on some variants of SUSv2 v3 or v4 (UNIX 98; 03 or POSIX.1-2008+XSI). And _POSIX_SOURCE is an obsolete way to define _POSIX_C_SOURCE = 1
They're the things you have to #define to get the prototype, and are known as feature test macros.
For example, the following code will susscessfully define the prototype for sigaction:
#define _XOPEN_SOURCE
#include <signal.h>
Including signal.h without that #define (or the others) will not define the prototype.
It is a Feature test macro.
Symbols called "feature test macros" are used to control the visibility of symbols that might be included in a header. Implementations, future versions of IEEE Std 1003.1-2001, and other standards may define additional feature test macros.

Resources