BSD C library for use on System V Release 4
===========================================

I ported this library to SVR4 for primary use on Amiga Unix, which is
a 680x0 based System V Release 4. Please see below for parts that are
machine (rather: cpu) specific, they're quite rare.


Copyright
=========

About 95% (or more) of this distribution is software developped at the
University of California, please check the Copyright headers in the
individual files for redistribution conditions.

I myself wrote some functions that emulate BSD system calls under
System V, that code is subject to a similar redistribution license as
the BSD code, look at the headers in the respecive files (mostly
lib/libc/amiga/sys/*).

Just to make that sure:

THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.



About the port
==============

This is the 4.3bsd-net2 libc, and as such should be fairly POSIX
compliant, as well as (contrary to the AT&T headers) being C++ compatible,
all function declarations appear inside macros that expand to a 

  extern "C" {
  ..
  }

block when compiled by C++.

I've already used this library in my AmigaDOS project called ixemul.library,
and it has proven to be very compatible to older BSD libraries, about the
only major difference being the new stdio implementation. However, this
new stdio is so nice, that you really won't miss the older one ;-))

Since the `in which header H is type T defined' is one of the most crucial
points if you want to be compatible to an existing OS, I tried to convert
most headers to use the same definitions that the system headers do, rather
than including headers from /usr/include from the BSD headers. Thus,
<sys/ioctl.h> really defines all ioctls, and does not try to include all
AT&T headers that may contain definitions of ioctls. This increases 
compatibility, at the risk of getting some defines wrong, ie. typos. To
prevent the most subtle bugs, I cross checked the typedefs in both series
of headers, and adapted the BSD headers to use same types as the AT&T 
ones (there's no sense in insisting that dev_t is short, if AT&T said
it's long...). This check should be 100%, since I automated it. Another
point where I tossed the BSD definition in favor of the AT&T one is with
sockets. 4.4 BSD uses new style socket addresses, and since I'm relying on
an AT&T library to deal with sockets, I had to use their definitions
here as well.


Things to watch out for:

o  <utmp.h>. This is the BSD utmp.h file. You just can't use the AT&T
   definitions, since BSD programs only know about one utmp file, not about
   the double nature of utmp/utmpx in SVR4. Since utmp and wtmp paths are
   different in BSD and SVR4, those files should not interfere, but if
   you want to generate executables that operate on the real system files,
   you'll have to do some porting work, I'm afraid.

o  <pwd.h>. This is the BSD definition of a passwd entry. Per coincidence,
   this structure is of the same size as the AT&T one, *and* all fields
   common to both structures are at the same offsets. So as long as you
   don't access `pw_change' or `pw_class', you're compatible with AT&T.
   BSD `getpw*' functions are currently disabled, because they require
   a different passwd database than currently used on SVR4.

o  <syslog.h>. This is the current BSD header, not the older one coming
   with the system headers. Since I don't use the AT&T syslogd, I don't
   know how (in)compatible they are.

o  probably other headers as well ;-)



Pecularities to my system
=========================

The used assembly files (originally for the hp300) are in MIT assembly
syntax, as used for example with SunOS. Symbols contain leading
underscores.  Since I already had done a gas port long time ago to
generate ELF object files, I didn't bother to convert those assembly
files into something the AT&T as can understand, but used gas to
compile (which also removes leading underscores ;-)). Since I can't
assume you have this gas (and I don't know yet if Commodore is willing
to distribute that on their system tape, it's sort of a crime to do
STABs in ELF for some people ;-)) I'm providing pre-compiled object
files for those files as well. See the compilation section below on
how to configure the Makefile to use those objects instead of trying
to recompile the sources.



Porting to a different version of SVR4
======================================

As stated above, this library is targeted for a 680x0 based system. As
of this, I used the hp300 related files from the BSD distribution. If you
want to go to another platform, you'll certainly have to replace the
following directories:

 o  include/machine
    This is currently sys/hp300/include, and could be replaced by 
    sys/i386/include for example.

 o  lib/libc/amiga/{gen,net,stdlib,string}
    This is currently lib/libc/hp300/{gen,net,stdlib,string}.
    If you don't find assembly files for your platform, use the generic
    C functions in lib/libc/{gen,net,stdlib,string}, you just have to
    enter them into the Makefile (the .c files are there, but not compiled
    by default).

 o  include/setjmp.h
    This contains a `#define _JBLEN	(1024 / 4)' at the start. The
    1024 really is `sizeof (struct ucontext)', but I couldn't include the
    headers defining this, or I'd get a bunch of incompatible header files
    included as well. Please make a safety check against the definition
    in your header files that ucontext has the same size on your cpu, or
    change the value accordingly.



BSD system call emulation
=========================

A few words to the strategy I used, for each call in lib/libc/amiga/sys:

dup2()
	Quite straight forward. Uses the F_DUPFD fcntl() command.

flock()
	This one is rather incomplete, but some incompatibilities are
	not solvable without kernel support.
	-  BSD can exclusively flock() files opened O_RDONLY. SVR4 can't,
	   since exclusive locks are emulated with F_WRLCK locks that
	   require write permission.
	-  fcntl() locking uses POSIX semantics for locking, whereas
	   flock() doesn't. This generates different behavior when closing
	   files that are locked. POSIX says that in that case all locks
	   are removed, BSD says that only on close of the last descriptor
	   referring to a locked file the file is unlocked. As above, this
	   behavior can't be achieved without kernel changes (and I don't
	   have AT&T sources ;-().

getdirentries()
	This should be a quite good emulation of the BSD system call, done
	using getdents() and converting the AT&T dirent structures into BSD
	ones.

[gs]etdomainname()
	Uses the systeminfo() system call. Should be 100%.

getdtablesize()
	Uses the sysconf() interface. Should be 100%.

[gs]ethostname()
	Uses the systeminfo() system call. Should be 100%.

getpagesize()
	Uses the sysconf() interface. Should be 100%.

getrusage()
	Uses times(). This is a very poor emulation, but I couldn't do
	better given the complete lack of kernel support for collection of
	process statistics (AT&T doesn't seem to believe in this ;-(). All
	you get is cpu usage information for children and your process.

select()
	Uses poll(). Should come quite close to the BSD system call, and is
	ways less buggy than the AT&T select() call. Only the range specified
	by the nfds parameter is accessed and changed in the infd, outfd 
	and excfd parameters. No innocent memory should be corrupted like the
	AT&T select() does. The flags used to map infd/outfd/excfd into poll 
	events could perhaps need some tuning, they're explained rather spongy
	in the man page, and boundery conditions will probably cause 
	incompatibilities.

[gs]etpriority()
	Uses the priocntl() interface. This is a new call of SVR4 that offers
	more flexibility than nice(2), and probably offers more trap doors
	as well. Currently, only manipulation of processes in the TS scheduling
	class are supported, no real time processes. This shouldn't be too
	much of a problem, since BSD programs don't expect to deal with such
	processes anyway ;-)). 

sigaction() and friends
	This is a bit a hacky mapping of BSD struct sigaction into AT&T struct
	sigaction. The reason this is necessary is, that BSD uses a struct
	sigaction that really is a struct sigvec, with the meaning of the
	SV_INTERRUPT bit inversed. To be able to use the signal code of
	BSD, you can't use AT&T struct sigaction, so all functions dealing with
	sigset_t (sigaction(), sigprocmask(), sigsuspend()) are routed over
	glue functions that convert back and forth between the two formats,
	allowing 1:1 usage of the compat-43/sigcompat.c stuff. Comes in
	very handy ;-))
	Note that the current implementation uses the _sigaction() entry
	in libc.so to perform the actual system call, since the library
	glue seems to require some fiddling with ucontext structures to
	implement saving/restoring of signal contexts in user mode (shudder..).

stat() and friends
	Uses the BSD <sys/stat.h> file, and remaps its layout into AT&T
	struct xstat. This finally gets rid of static function
	definitions in header files... Please check the used struct xstat
	if it equals the definition in /usr/include/sys/stat.h if you're
	running a system other than Amiga Unix (2.03, if that matters).
	This also fixes a bug upto 2.03, that returned st_blksize == 1k
	for ufs files. It now forces st_blksize to 8k if filetype is ufs.

utimes()
	Uses utime().

wait4()
	Done with the (rather weird) waitid() call. Same sighs apply as with
	getrusage(), you can't get more information than cpu usage from the
	child that just died, no statistics are available.



Sockets and the net/ functions
==============================

Since sockets are implemented by AT&T proprietary (blech) emulation code,
all I could do is extract the bare minimum of needed object files from
libsocket.a, and link them with the rest of the library, hoping to minimize
that way the number of imported bugs. The net/ directory is plain BSD
again, no AT&T copyrights here.

Note, that there is a fundamental difference between the ways how SVR4
and BSD deal with DNS queries:

SVR4	uses two different socket libraries (libsockdns.so, libsockhost.so),
----	from which you link one to be libsocket.so.

BSD	uses only a DNS net library. This is possible, because BSD datagram
---	sockets, when connect()ed, return ECONNREFUSED if the target socket
	is not bound. That way, if there's no DNS daemon, there's no query
	timeout, and the lookup code can procede to check the /etc/hosts
	file without noticeable delays for the user.

Since I couldn't get the ECONNREFUSED behavior with AT&T socket emulation
(is it possible? The BSD comments state that this should work starting with
4.3 socket code), I chose a solution I've seen on Irix. It works like this:

o  if you want DNS resolution of addresses, you don't have to do anything,
   that's the default.
   If you want another nameserver to be used than your machine, don't forget
   to add an appropriate `nameserver' entry into /etc/resolv.conf.

o  if you want only /etc/hosts resolution of addresses, create an 
   /etc/resolv.conf file that contains this line:

     hostresorder local

   This tells the resolver to bypass DNS queries and only search the 
   /etc/hosts file. Note that this is the only option supported, don't try 
   other Irix keywords ;-)

By using this solution, you don't have to temper with crucial system
libraries, I really prefer it to the SVR4 variant.

I've heard that there is a paper detailing implementation of socket
emulation in SVR4. If you could point me at an ftp'able copy of this
paper I'd be most grateful!


What happened to libnsl.so
==========================

That's another one of those proprietary AT&T libraries, but this one
was simple enough for me to provide a replacement for that I wrote
myself, and is thus not subject to AT&T software hoarding. Note however,
that the replacement heavily relies on a conforming /etc/netconfig file,
there's hardly any redundant syntax checks performed on the file, if you
got it wrong, the functions will probably just dump core. If you want to
refine them, the source is in lib/libc/nsl/getnetconfig.c. There's a short
test program in that directory as well, that just dumps the current
database. Link once with the AT&T library, and once with the getnetconfig.o
file, and diff both outputs. They should be identical.



Compilation
===========

(At least under Amiga Unix) just cd into lib/libc, and edit the Makefile.
You find a few macros at the top you can modify to tailor the library to
your system. Read the explanations in the Makefile for their meaning.
A side note to BSD_HEADERS: the path given here can be different than what
you'll use to install the headers in the system. On my system, I have a
symbolic link that points from /usr/local/bsd43include into the source
tree where I keep the whole library. BSD_HEADERS points into that internal
place, not at /usr/local/bsd43include.

After changing the Makefile, you should be able to just start make and
get a libbsd43.so:

	make all

If you have to fix some problems, you may find it useful to just `make' in
the respective directory and then use

	make loadlib

in lib/libc, this target doesn't scan the whole source tree for dependencies,
and just builds the library unconditially from the compiled object files.

Note: compiling sources that use rather complex dependencies I discovered 
      that the AT&T make command doesn't get dependencies right in some
      cases. The easiest solution to fix the problem is to use GNU make. I
      doubt that the Makefiles used in this library are too complex for the
      system make, but if you should face a situation that looks weird, before
      trying to look for own bugs, try GNU make!



Installing
==========

The generated library should go into /usr/lib (if you want to place it
somewhere else, you'll have to define LD_LIBRARY_PATH to include that 
directory before starting any program needing that library):

	cp libbsd43.so /usr/lib

Header files can go everywhere you like, but the preferred place to put 
them is

	/usr/local/bsd43include

That way people using the same library don't have to change Makefiles
all the time. Thus, normally do (from the top of this distribution):

	ln -s `pwd`/include /usr/local/bsd43include

It should be obvious that both actions, copying the library into /usr/lib
and creating the symbolic link to the header files requires special
privileges, thus you probably want to execute those commands as root.



Using the library
=================

Using this new library is very simple. Given a program foo.c, and assuming
you installed the headers at the recommended place, you just enter:

  gcc foo.c -I/usr/local/bsd43include -o foo -lbsd43

This even holds if foo.c contains network calls, you can forget about
`-lsocket -lnsl' when using `-lbsd43'!!



Man pages
=========

I moved all man pages into a central directory, lib/libc/man. If you want
to install them, remember to get the new BSD macro packages, those man
pages can't be converted with the traditional `nroff -man', you'll have
to use `nroff -mandoc'.



So.. good luck getting the library up, if you have problems, suggestions,
improvements, etc., you can reach me as

<wild@nessie.cs.id.ethz.ch>
<wild@amiga.physik.unizh.ch> (this one is directly SMTPable from outside).

Flames can be mailed to <bitbucket@nessie.cs.id.ethz.ch>, but please don't
overfill nessie's /dev/null ;-))


Markus M. Wild
