This file is the README for BSD::Sysctl version 0.02

INSTALL

perl Makefile.PL
make
make test
make install

Building this module requires a FreeBSD system and a C compiler.
Support for OpenBSD and NetBSD will appear in future releases. In
theory, any system that uses a sysctl interface to the kernel should
be able to be handled by this module.

This module requires the following modules for thorough testing:

  Test::More

This module can optionally use the following modules for
testing (their absence is not a problem).

  Test::Pod
  Test::Pod::Coverage

HELPING

Patches welcome!

If you would like to see this module work on other operating systems,
but don't particularly wish to hack on the source yourself, and you
have a publically accessible machine on the net, and you are fine
with the idea of giving me an account on said machine, then drop
me a line.

I will send you my public key for connecting via ssh. All
I need is a shell and a C compiler, and I give you my word that I
will not do anything evil. If required, I will connect only from
a fixed address (which would allow you to set up an AllowUsers
USER@HOST rule in your sshd_config file).

IMPLEMENTATION

A sysctl variable is usually specified symbolically, such as
"net.inet.tcp.sendspace" (also referred to as a MIB). Internally,
the kernel operates on an equivalent numeric list (also referred
to as an OID). Furthermore, different variables contain different
values. They may be numeric or character strings, they may be a
single value, a list of values, or a set of key/value pairs.

When a sysctl variable is fetched, the module first asks the kernel
to convert the symbolic name to its numeric equivalent.  If this
step fails, the module considers that the variable does not exist.
This step is handled by _mib_info().

If this step succeeds, the module now has the list of numeric values
(the OID) that corresponds to the variable. It then performs a
second call to ask the kernel how the result is to be formatted.

It is a reasonable assumption to imagine that different BSD variants
(perhaps even between major releases of the same operating system)
will use different techniques for performing this step, and so the
XS code will probably require a certain amount of conditional
compilation.

In FreeBSD, the formatting information is returned as a string. For
instance, "I" is an integer, "IU" is an unsigned integer, "LU" is
an unsigned long, "A" is an ASCII string.  More complex variables
return the name of the C struct to use to decode the result, for
instance the formatting code for "vm.loadavg" is "S,loadavg", which
implies that the result should be cast to a "struct loadavg".

Sometimes a number of auxilliary header files need to be included
in order for the header file that defines the structure in question
to be specified completely. The eg/sizeof.c is handy for figuring
out what is required.

A performance optimisation concerning the formatting information
is to map the string names to integers (this means that the results
can be dealt with in a switch statement, rather than a long if/else
chain. The mapping table is stored in the mibfmt.map file, and is
processed by Makefile.PL to produced the C header file needed by
the XS file.

Once the formatting key has been converted to an integer, the
information is saved in the %MIB_CACHE hash table.  Each key
points to a packed list of integers:

  +-------------------------+
  | format value            |
  +-------------------------+
  | count of remaining ints |
  +-------------------------+
  | oid element 1           |
  +-------------------------+
  | oid element 2           |
  +-------------------------+
  | ...                     |
  +-------------------------+
  | oid element n           |
  +-------------------------+

This information can be unpacked in Perl-space with the following
unpack() template: 'i i/i'.

When adding other operating systems, new format values may be
appended to the end of the mapping file.

After this step has been performed, _mib_lookup() may then
proceed with fetching the value associated with the variable.
The system call is performed, and, assuming no errors, the
results are formatted (according to what %MIB_CACHE indicates, and
a scalar, or a reference to an array or hash, is returned.

Reading the source to the sysctl binary is very instructive.  (i.e.
/usr/src/sbin/sysctl/sysctl.c on FreeBSD).
