Btw, I just finished an analysis of what is in libucb. (I've not check the other libraries, most especially termcap, yet.) My findings show that there is a lot there that could simply trivially be eliminated. Here's the detailed analysis:
First I started by comparing differences between libc and libucb implementations: Differences in libucb implementation ------------------------------------ psignal() - UCB flushes stderr first then calls libc version. The libc version uses an unbuffered write() to stderr (2). Note that the UCB flushing behavior is not documented. bcmp() - UCB Just calls stock _memcmp. No functional difference otherwise. Could be eliminated. bcopy() - UCB calls _memmove, if len > 0. Stock calls memmove unconditionally. Should not have any functional difference, and hence can be eliminated. ftime() - UCB asks gettimeofday for the local timezone, and uses it. libc optimizes by using local values within libc and a "guranteed to succeed" _ltzset(). Otherwise no functional difference. Could be eliminated. getwd() - Identical implementations. Could be eliminated. index() - UCB has local implementation, but libc just calls strchr. Could be eliminated. rindex() - UCB has local implementation, but libc just calls strrchr. Could be eliminated. nice() - UCB has local implementation based around setpriority() and getpriority(). libc uses a system call, and is hence less prone to races and faster. Calling semantics are identical, could probably be eliminated. nlist() - UCB has local implementation supporting COFF (a.out). This one we would have to continue to provide for legacy apps. rand() - Both use the same polynomial PRNG, but UCB returns the full result, whereas libc discards the lower 16 bits provides just 15 bits of randomness. (UCB returns 31 bits, although the lower bits are particularly random.) This difference could be enough to break poorly written applications, so this has to continue to be supplied. readdir() - Different implementations, but apparently identical semantics and structures. Could probably be eliminated. re_comp() re_exec() - These are backed by nearly identical sources, with just some stylistic and lint fixes (e.g. substituting 0 for NULL and casting). Could be eliminated. scandir() alphasort() - Nearly identical implementations, and identical semantics. Could be eliminated. setbuffer() setlinebuf() - UCB mucks in internals of libc stdio (urk!) libc just uses setvbuf(). This should almost certainly be eliminated, as nothing should be mucking around inside the internals of libc stdio structures. Semantically identical. (Note UCB version seems to have inlined copy of setvbuf code.) sys_siglist - UCB has this. libc has _sys_siglist. They are almost identical, except some of the strings are slightly different. Could probably be made an alias in UCB for _sys_siglist. statfs() fstatfs() - UCB implements on top of statvfs/fstatvfs. libc uses a syscall. Same semantics, could probably be eliminated. statfs64() fstatfs64() - Whoa?!? 64-bit versions of these calls, only provided by libucb. Not sure why, since no applications should ever use them. This looks like it was integrated at the time of the original 64-bit port, without ever making it available in any public API. These could probably safely be eliminated as they have never been documented. times() - Difference is value returned. UCB returns 0 on success, libc returns a tick count. Cannot be eliminated. wait4() - UCB returns EINVAL if options contains WCONTINUED, whereas libc allows (XPG4.2.) Otherwise they are identical. I think this could safely be eliminated. If not, it could be replaced with a thin wrapper which calls the libc version after checking for WCONTINUED in the options arg. wait3() - Both are just simple wrappers around wait3. Can be eliminated. flock() - Only UCB has it, as a thin wrapper around fcntl(). Perhaps we should provide it in libc as well? In the mean time we have to leave it. getdtablesize() - Identical implementations, could be removed. gethostid() - Functionally equivalent implementations. The libc version is slightly more efficient. The UCB version could be eliminated. gethostname() - Functionally identical, could be eliminated. sethostname() - Nearly identical, except UCB first checks to make sure uid == 0 and returns EPERM if not. (Same errno returned by syscall btw.) (Not RBAC compliant.) UCB version could be eliminated. getpagesize() - Identical implementations. Could be removed. killpg() - identical, except libc version takes pid_t instead of int for pgrp. However, binary they are identical, so UCB version could be eliminated. mctl() - UCB supplies thin wrapper around memcntl. Could be supplied in libc as well. Needs to stay otherwise. reboot() - both just call uadmin, after processing args. libc adds support for RB_DUMP that UCB lacks. libc also passes through boot arguments, whereas UCB suppresses them. Note however, that no applications are likely to be bothered by this difference. We could probably safely just eliminate the UCB wrapper. setpgrp() - Different calling conventions, we have to retain it. The UCB version is a trivial wrapper around setpgid. _doprnt() _getarg() _mkarglst() - These are private to internal libc STDIO. We should not need to export them. fopen() - UCB is functionally and semantically equivalent to libc. Could be removed. freopen() - Identical, except for libc XPG6 semantics that *might* be applied, optionally (and not relevant to legacy apps.) Also, libc is thread safe. UCB version could be removed. fopen64() - Huh? Another weird 64-bitified API that should never have happened and was never publicised. It should be safe to remove this. fprintf() printf() vfprintf() vprintf() - These are standards-conformat APIs. They should just work. The libc versions benefit from being MT async safe. The main other difference bewing that the libc version has some support for additional format specifiers. ("ll", "Q", "hh"). libc can also support wide characters. We can probably safely remove the UCB versions. vsprintf() sprintf() - Semantically identical, the UCB version can be removed. Summary: -------- Only the following functions are still required in libucb, as far as I can tell: nlist() rand() times() flock() (unless we provide one in libc) mctl() (unless we provide one in libc) reboot() (maybe, see comments above) setpgrp() Additionally, we'll have to have a linker alias for sys_siglist to point to libc's _sys_siglist. At this point, I think libucb becomes quite small indeed.