Functions (limited to libc and "system" ones), general often-used concepts and variable types. Include known flaws, work-arounds, autoconf tests and general comments from past experiences.
If you find flaws or have additional data to offer, please mail me. My email address is visible at the bottom of the page. This page is destined to always be "under construction".
Related useful resources: predef.sf.net, Unix Incompatibility Notes, Tips For Writing Portable C
Function | Issues |
---|---|
basename | FreeBSD 3.4 does not include the standard function basename(). |
bcopy | Old-style BSD function, use memcpy() for portability |
bzero | Old-style BSD function, use memset() for portability |
gettimeofday | Not available on Windows, otherwise widely available. clock_gettime() is a newer POSIX/TSUSv2 function with higher resolution. |
getaddrinfo | Only available in recent modern operating systems
(gethostbyname() must be used on the others). NI_WITHSCOPEID (not present in
mingw, glibc 2.3.2, Tru64 5.1, IRIX 6.5.22) and AI_NUMERICHOST (not present in
AIX 4.3) are not universally available even if the getaddrinfo() function is
present Using the PF_UNSPEC option on Linux hosts that are ipv6-enabled but that doesn't have the ipv6 kernel module loaded cause very slow name resolves. This is usually worked around by first trying if a ipv6 socket can be made and if not, no ipv6 resolves are attempted (PF_INET). |
gethostbyaddr_r | Not needed on Windows, HP-UX 11 and AIX 5
(since gethostbyaddr() is then thread-safe on its own). Not existant on older
platforms. Three different APIs: 5 arg version: int gethostbyaddr_r(char *address, int length, int type, struct hostent *he, struct hostent_data *data) 7 arg version: struct hostent *gethostbyaddr_r(char *address, int length, int type, struct hostent *he, char *buffer, int bufsize, int *errno) 8 arg version: struct hostent *gethostbyaddr_r(char *address, int length, int type, struct hostent *he, char *buffer, int bufsize, struct hostent **hep, int *errno) |
gethostbyname_r | Not needed on Windows, HP-UX 11 and AIX 5
(since gethostbyname() is then thread-safe on its own). Not existant on older
platforms. Three different APIs. AIX4, Digital Unix/Tru64, HPUX 10 use 3 arguments: int gethostbyname_r(char *hostname, struct hostent *hostent, struct hostent_data *data) Solaris (needs to be linked with -lnsl) and IRIX use 5 arguments: int gethostbyname_r(char *hostname, struct hostent *hostent, char *buffer, int buflen, int *h_errnop) Linux uses 6 arguments: int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) |
gethostbyname | Found in different libs in different operating systems. Could be one of these: -lnsl (Solaris), -lsocket, -lws2_32 (Windows), and -lnet (BeOS). See also gethostbyname_r |
localtime_r | Not present in all unixes. Broken implementation in HPUX 10.20 (it returns an 'int' instead of a pointer - is that 0 for success?) |
strerror_r | Not present everywhere (like Windows, Solaris 7). But when it is, there's a POSIX way (int strerror_r(int errnum, char *buf, size_t n)) and there's a glibc way (char *strerror_r(int errnum, char *buf, size_t n)) |
inet_ntoa_r | Not present in all unixes. |
strtok_r | Not present in all unixes. Standardized in UNIX98 (aka SUSv2) |
getpass_r | Not present in all unixes. In fact, this is rarely available. (SCO Unix has it) |
gmtime_r | Broken implementation in HPUX 10.20 (it returns an 'int' instead of a pointer - is that 0 for success?) |
select | Windows quirks: you can only select on sockets. You
cannot know if a FD_SET() would overflow the buffer since the file descriptor
numbering starts way above 0 and comparisons against FD_SETSIZE are not
working. FD_SETSIZE is typically set very low (64) by default. Many unix versions allow FD_SETSIZE to be re-defined at compile time, but Linux does not. Linux has odd semantics, the following is from the BUGS section of select(2) Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block. |
poll | Not existing on old unixes. Broken implementation in Mac OS X at least up to 10.4 and earlier. Up to 10.3 you could check for a poll() that works with all arguments zeroed. The 10.4 bug is more obscure an I don't know of any way to detect it without checking for OS. |
snprintf | Essential function that is lacking in older unixes (SunOS) and Windows. Different implementations return differen values in case of prevented overflow. autoconf macro for C99-compliant snprintf trio *printf code |
sprintf | Returns either a 'char *' as a pointer to the output buffer (SunOS, 4.3 BSD) or an int as the length of the output data (most others, POSIX). |
strcasecmp | Some platforms (Reliant and UnixWare) have this in the resolve lib, requiring -lresolve to link fine. |
socket | Needs -lnsl -lsocket in LDFLAGS to link on
Solaris
On Win64 it returns a SOCKET which is 64 bits, while (all?) other systems return an int, 32 bits. |
sigaction | HPUX doesn't have SA_RESTART, but instead it defaults to the same behaviour as other systems that do have gets when ANDing out the SA_RESTART bit from sigact.sa_flags |
Concept | Description |
---|---|
Non-blocking sockets | Done in lots of different ways:
The POSIX approach (known to not work on SunOS 4, AIX v3 and BeOS - although the function and defines are present) fcntl(socket, F_SETFL, flags | O_NONBLOCK) BSD-style ioctl(socket, FIONBIO, &flags) Windows-style ioctlsocket(socket, FIONBIO, &flags) AmigaOS-style IoctlSocket(socket, FIONBIO, (long)1) BeOS-style setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)) |
Avoiding SIGPIPE | Done in several ways: Ignore signal (using sigaction() or signal(), the latter more widely available) Mac OS X 10.2 and later (at least): setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) Most other systems support send/recv(x,y,z, MSG_NOSIGNAL) |
Building thread-safe | -D_THREAD_SAFE -D_REENTRANT (Solaris, HPUX) and more? [FILL IN] |
libc | Windows quirks: the libc is provided by the compiler, not by the operating system. Thus, various libc function calls may differ between compilers. |
case insensitive string comparisons | Most systems: int strcasecmp() Windows: int strcmpi() or int stricmp() |
writeable argv[] | Many systems allow programs to overwrite the argv[] strings to hide data from appearing in ps outputs (Linux, Solaris 7, HP-UX 11, Tru64 V5, IRIX 6.5) |
inline | Was not a standard keyword until C99. Before that, compilers provided various own approaches (gcc supports inline since very long). |
Type | Issues |
---|---|
time_t | Often a signed 32bit type, sometimes unsigned 32bit (OpenVMS), and sometimes still 32bit even when running in a 64bit arch (AIX) and even sometimes 64bit on 32bit systems (VS2005) |
size_t | POSIX type not always present on old systems. strlen() and family returns size_t in POSIX |
ssize_t | Commonly used signed version of size_t. Not present on numerous systems. |
in_addr_t | Not present on many pre-POSIX systems. Functions that otherwise use in_addr_t usually use int on those. |
socklen_t | Not present on many pre-POSIX systems. Functions
that otherwise use socklen_t usually use int on those.
AIX 4.2 curiously uses an unsigned type for this. (AIX -4.1 was int, AIX 4.3+ is socklen_t) |
struct sockaddr_storage | Not present in AIX 4.3 even though it has getaddrinfo() and other IPv6-ready functions |
off_t | POSIX type for file sizes. Not present on older systems. Usually 32 or 64 bit. |
Thanks!