'\"!  tbl | mmdoc
.if n .pH port.chap03 @(#)chap03	40.4
.\"
.\" Porting manual: System Interfaces & Libs
.\"
.\" NOTE: Be sure to replace all "<TAB>" sequences with a real tab
.\"       when you get this.  Also, replace all real tabs with "<TAB>"
.\"       before sending this through mail.
.\"
.\" Ps = POSTSCRIPT
.\" Sd = X11/NeWS
.\" Cs = CSCRIPT
.\" At = AT&T SVR4.0
.\"
.ds Ps P\s-2OST\s+2S\s-2CRIPT\s+2
.ds Sd \s-2X11/Ne\h'-0.2n'WS\s+2
.ds Cs \CS\s-2CRIPT\s+2
.ds At "AT&T SVR4.0
.\"
.BK  "Porting the X11/NeWS Server"
.CH "System Interfaces and Libraries" 3
.H 1 "System Interfaces and Libraries" 
.H 2 "Introduction"
This section describes the library functions and system calls needed in
order to port \*(Sd to a new hardware and/or software platform.  The
software is configured for \*(At, so this chapter is simply
a reference and an explanation for the mechanism that \*(Sd uses to
isolate itself from the host operating system.
.P
The library functions and system calls can be broken down into four
categories:
.BL
.LI
C Library
.LI
BSD Emulation Library
.LI
Non-Portable System Interface
.LI
Memory Allocation.
.LE
.H 2 "C Library"
.P
\*(Sd assumes that the host system's
.UI libc
library implements many of the common routines associated with
a general UNIX C library, such as the one described in Section 3c
of the \f2Unix System V Release 4.0 Programmer's Reference Manual\f1.
It also expects to find the set of UNIX System calls
described in Section 2 of the same manual.
.P
\*(At supplies all these needed functions, so no extra
work is required.  Most other Unix systems
based on Bell Labs V7 UNIX should also satisfy this requirement.
Only when porting to a non-UNIX environment (OS/2, Macintosh), or a
non-hosted environment (a graphics terminal) will these routines need
to be provided or emulated.
.H 2 "BSD Emulation Library"
\*(Sd needs to be compiled on a
system with a minimal BSD-like environment.
\*(Sd uses some routines present in the system libraries
under 4.3 BSD and SunOS, but not present in \*(At
.P
The
.UI BSD
Emulation Library includes the following non-networking related functions:
.TS
tab (%) box;
l l.
Routine%Description
_
\f4bcmp\f1(3)%compare two arbitrary sequences of bytes
\f4bcopy\f1(3)%Copy an arbitrary sequence of bytes
\f4bzero\f1(3)%Fill a block of memory with zeros
\f4getpagesize\f1(2)%Get the VM page size
\f4getwd\f1(3)%Get Working Directory
\f4index\f1(3)%Find first occurrence of a char in a string
\f4rindex\f1(3)%Find last occurrence of a char in a string
\f4vfork\f1(2)%A faster version of fork()
.TE
.P
When porting to a new environment some of these routines may exist in
your libraries, and some may not.  For example, \*(At does not provide all
these routines, so you must either use an equivalent routine or
implement the routine from scratch.
.P
Emulation routines are provided in the directory
.UI ~/portable.
The library
.UI libportable.a ,
which is built from routines in
.UI ~/portable
needs to be installed in a
convenient place so that it can be used when building the rest of the
server.  The recommended place is in
.UI $(DESTDIR)/usr/lib
because that directory is always placed in the library search path by the
.UI Makefiles
which are used to build \*(Sd.  See 
.UI Master.cfg 
for the definition of the macro
.UI BSDEMULATIONLIB .
.P
Below we describe the routines needed to support \*(Sd under
\*(At.  The routine name is followed by the
C declaration assumed by the code that uses it.
.H 3 "\f(CWbcopy()\fP"
.SS
bcopy(b1, b2, length)
char *b1, *b2;
int length;
.ft1
.SE
.H 3 "\f(CWbzero()\fP"
.SS
bzero(b, length)
char *b;
int length;
.ft1
.SE
.H 3 "\f(CWbcmp()\fP"
.SS
int bcmp(b1, b2, length)
char *b1, *b2;
int length;
.ft1
.SE
.P
These three functions operate on
variable length strings of bytes. They do not check for null bytes
as the routines in \f(CWstring(3)\fP do.
.P
\f(CWbcopy()\fP copies 
.UI length 
bytes from string b1 to the string b2.
Overlapping strings are handled correctly.
.P
\f(CWbcmp()\fP compares byte string b1 against byte string b2,
returning zero if they are identical, non-zero otherwise.
Both strings are assumed to be length bytes long. \f(CWbcmp()\fP of
.UI length 
zero bytes always returns zero.
.P
\f(CWbzero()\fP places length 0 bytes in the string b.
.P
Under \*(At, the functions \f(CWmemcpy(), memset(),\fP and
\f(CWmemcmp()\fP are used to implement these routines.
.H 3 \f4getpagesize()\fP
.SS
int getpagesize()
.ft1
.SE
.P
This function returns the number of bytes in a memory page.
Page granularity is the granularity of many of the memory management
calls.
The page size is an operating system page size and might not be the
same as the underlying hardware page size.
.P
This function is used to develop a better memory allocation method by
aligning memory requests on page boundaries.  See also
.UI palloc() .
.P
This function can be emulated under AT&T SVR3 with
.UI "#define getpagesize() NBPP"
where
.UI NBPP
is the value found in the system header file
.UI <sys/immu.h>.

.H 3 "\f(CWgetwd()\fP"
.SS
char *getwd(pathname)
char pathname[MAXPATHLEN];
.ft1
.SE
.P
Returns a string whose contents is the name of the current working
directory.  Under \*(At, this can be emulated with
.UI getcwd() .
.P
.H 3 "\f(CWindex()\fP"
.SS
char *index(string, ch)
char *string;
int ch;
.ft1
.SE

.H 3 "\f(CWrindex()\fP"
.SS
char *rindex(string, ch)
char *string;
int ch;
.ft1
.SE
.P
These functions find the first occurrence of a specified character in a
given string.  If found, a pointer to it is returned, if not then
NULL.
\f(CWindex()\fP starts at the beginning and searches to the end;
\f(CWrindex()\fP does the reverse, starting at the end and searching to
the beginning.
.P
The routines
.UI strchr()
and
.UI strrchr()
under \*(At provide the same behavior under different names.
.P
.H 3 "\f4random()\fP"
.SS
long random()
.ft1
.SE
.H 3 "\f4srandom()\fP"
.SS
srandom(seed)
int seed;
.ft1
.SE
.P
These functions return successive pseudo-random numbers in the range of
0 to (2**31)-1 by using a non-linear additive feedback random number
generator employing a default table of size 31 long integers.
The period of this random number generator
is very large, approximately 16*((2**31)-1).
.P
.UI random()
and
.UI srandom()
have almost the same calling sequence and
initialization properties as 
.UI rand/srand.
The difference is
that 
.UI rand(3C)
produces a much less random sequence--in
fact, the low dozen bits generated by 
.UI rand 
go through a
cyclic pattern.
.P
For the initial \*(At release, the functions
.UI srand()
and
.UI rand()\fP
are used instead.  As noted above, this will affect the quality of the
results, so a production release should implement a higher quality
psuedo-random number generator (see
.UI drand48 ).
.H 3 "\f(CWvfork()\fP"
.SS
#include <vfork.h>
int vfork()
.ft1
.SE
.P
.UI vfork()
can be used to create new processes without fully
copying the address space of the old process, which is
inefficient in a paged environment. It is useful
when the purpose of
.UI fork(2)
would have been to create a
new system context for an
.UI execve(2) .
.UI vfork()
differs from
.UI fork()
in that the child borrows the parent's memory and
thread of control until a call to
.UI execve(2)
or an exit (either by a call to
.UI exit(2)
or abnormally.) The parent process
is suspended while the child is using its resources.
.P
As used in \*(Sd,
.UI vfork() 
does use the special semantics associated with it, so it can be replaced with
\f(CWfork()\fP under AT&T SVR4.0.
.H 2 "Non-portable System Interface"
The final required set of routines is termed the high level
.I "Non-portable Systems Interface,"
or NPSI for short.
This library is used by the server. Note that
Shapes
and the development tools do not require these routines.  Therefore,
NPSI is not needed until you actually are working on the server
itself.
Detailed NPSI information is provided in later chapters.
.H 2 "Memory Allocation"
There are several memory allocation schemes available.  These range
from
a simple one
based on \f(CWmalloc()\fP and \f(CWfree()\fP to an optimized one which
has knowledge of memory page sizes and kernel memory paging and
swapping policy.
For an initial port we recommend using the scheme based on
\f(CWmalloc()\fP.
See the file
.UI ~/usr.bin/xnews/xnews/palloc/debugpalloc.c
for more detail.  The ``non-debugging'' \f(CWpalloc()\fP routines try
to localize common memory references in ``pools'', in order to reduce
the virtual memory working set size used by the server.
