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.

Reply via email to