I, too, "value your privacy" but unlike most I think it is priceless and fundamental. Privacy Policy

Unix defects

This tries to list all the defects that are present in Unix, an OS from the early 70's. I consider "Unix" what current Unix clones (BSDs, illumos, Linux, …) have implemented.

None of this should be present in brand new systems except within a cleanly-separated compatibility layer (like Plan9 ape).

NULL-Terminated lists

Slow to parse
Time taken to obtain the length increases with each byte aka O(n) while length prefix is constant-time aka O(1).
Inefficient & Unsafe slices
For a slice without modifying the source, you still need to copy the wanted part and terminate it with NULL. While with length prefix you can reuse the source as-is via an offset (or pointer) and setting a different length.
Unsafe
How do you handle NULL being present in the middle of the list? Or NULL being absent?

And as C doesn't have a specific type for strings (char represents a character in the same way a "word" of memory represents some kind of word), the defects applies to all lists. This is why most of the C API regarding strings cannot be used safely (strcpy vs strncpy or just memcpy), or why so many third-party C libraries APIs are architecturally broken.

errno

Implementation-defined, had to become stored in thread-local-storage in modern systems so it's not actually a global variable… enjoy.
It's also a very poor way to handle errors, if you're wondering where the occasional "Error: Success" comes from: This is it.
And of course, it means having a pretty much static amount of possible errors.

nsswitch.conf, resolv.conf, …

Because those configuration files ought to be trully language-independent rather than somewhat stuck to libnss (not Netscape/Mozilla SSL/TLS library) and libresolv by design and prone to creating a lot of problems when used by other programs (such as not dealing correctly with the options of resolv.conf).
Please consider: Clean ABI; Proper servers; Virtual filesystems (could look like tcb shadow for passwd).
See Also: The problem with nsswitch for the security angle.

By the way, while (getaddrinfo(3), gethostbyname(3), …) are part of the POSIX standard, other functions like res_query to actually query DNS records (needed for MX, SRV, …) aren't standardized.

getaddrinfo(3)

Related to nsswitch.conf.

Compare this to Plan9 dial(2) which also has a nice NetConnInfo structure.

gethostbyname(3)

The older brother of getaddrinfo(3), it doesn't handles multiple records.

Filesystem I/O

Removable storage has been a thing on computers since more or less the beginning (punched cards, tape, floppies, CDs, …). Buggy storage devices also happen too often to be ignorable. Networked filesystems and services exposing a filesystem (Plan9, FUSE) have also been there for a long time.
Yet somehow, even modern Unixes usually cannot handle them properly, leaving uninterruptible processes if they happen to use I/O syscalls on an errorneous target.

Even BSD sockets work better on this front (which is probably why libnfs exists).

Filesystem Queries

Most network protocols today have the ability to ask the server to search inside some database. Meanwhile Unix filesystems don't even integrate glob, instead this function is stuck to standard libraries. With people relying on third-party I/O-trashing central databases/indexes (again removable/network storage are a thing) from non-standard solutions like locate that are difficult to reuse in other programs.
Meaning that applications also often roll their own solution.
Compare this to Haiku

Filesystem lack of transactions

On Unixes, thanks to the lack of grouping writes into transactions (ie. BEGIN … COMMIT in SQL). The only way to get atomicity is to do manual Copy-on-Write: Copy to a temporary location, write there and then rename to the final destination, meaning you need to have full control over it to avoid race-conditions. And for atomicity over multiple files, a common parent directory is needed, otherwise you're in a bad state between the first rename and the last one.

It also means:

/dev isn't a virtual filesystem

Should be noted that Linux's devtmpfs somehow fixed none of the above.

/dev should be a virtual filesystem, say something that points to a device manager like udev or the kernel itself. Similarly to how it's done for /proc and /sys on Linux.

ulimit

It should have been something like cgroups/Plan9-namespaces, instead you get broken-by-default soft limits which can be overridden at any moment by applications, therefore useless. And hard-limits that can realistically only be set per-user/per-group.
Ever wanted to limit the usage of one software, like say the memory used by the browser? Well you can't with limits, and apparently cgroups have side-effects…

See Also