=head1 Hacking INN

This file is for people who are interested in making modifications to INN.
Normal users can safely skip reading it.  It is intended primarily as a
guide, resource, and accumulation of tips for maintainers and
contributors, and secondarily as documentation of some of INN's internals.

This is $Revision: 1.5 $ dated $Date: 2000/04/06 02:27:38 $.

=head1 Configuring

INN uses autoconf to probe the system on which it is being compiled and
adjust how it does things to try to be as portable as possible.  The shell
script configure at the top level of the source tree is autogenerated by
autoconf from F<configure.in>, and F<include/config.h.in> is autogenerated
by autoheader from F<configure.in> and F<include/acconfig.h>.  At
configure time, configure generates F<include/config.h> and several other
files based on options it was given and what it discovers about the target
system.

All modifications to configure should instead be made to F<configure.in>.
Similarly, modifications to F<include/config.h.in> should instead be made
to F<include/acconfig.h>.  The autoconf manual (available using info
autoconf if you have autoconf and the GNU info utilities installed on your
system) is a valuable reference when making any modifications.

To regenerate configure, just run C<autoconf>.  To regenerate
F<include/config.h.in>, run:

    autoheader -l include

to tell it where to find acconfig.h.

The generated files are checked into the CVS repository so that people
working on INN don't have to have autoconf on their system, and to make
packaging easier.

At the time of this writing, autoconf 2.13 is required.

The supporting files for autoconf are in the F<support> subdirectory,
including the files F<config.guess> and F<config.sub> to determine the
system name and the files F<ltconfig> and F<ltmain.sh> for libtool
support.  The latter two files come from the libtool distribution; the
canonical version of the former are maintained in the autoconf repository
but the latest versions are available with the latest release of autoconf,
automake, or libtool.

For maintainers with CVS access, these four files are on a separate vendor
branch (the 1.1.2 branch in the repository).  When a new version of
libtool is released, put those four files in a directory and import them
onto that branch with something like

    cvs import -m "Import of libtool 1.4 support files" -b 1.1.2 \
    inn/support FSF LIBTOOL-1_4

(all on one line) and then merge that vendor branch into the mainline.
See the cvs manual under Tracking Sources and specifically Multiple Vendor
Branches for more details.

This process can optionally be done with just F<config.guess> and
F<config.sub> when new versions of those are released between libtool
releases.
    
INN should not compile with libtool by default, only when requested, since
otherwise normal compilations are quite slow.  (Using libtool is not
without some cost.)  Basic compilation with libtool works fine as of this
writing, with both static and shared compiles, but the dependencies aren't
quite right for make -j using libtool.

=head1 Documentation

INN's documentation is currently somewhat in a state of flux.  The vast
majority is still in the form of man pages written directly in nroff.
Some parts of the documentation have been rewritten in POD; that
documentation can be found in F<doc/pod>.  The canonical source for
F<README>, F<README.perl_hook>, F<INSTALL>, F<NEWS>, and this file are
also in POD.  In addition, DocBook SGML versions of the POD documentation
are included in the CVS tree (although not in releases at this time, since
they're programmatically generated and occasionally of somewhat poor
quality) and periodically updated both for the use of DocBook translators
and to make conversion to SGML easier if necessary down the road.

If you're modifying some part of INN's documentation and see that it has a
POD version in F<doc/pod>, it's preferred if you can make the
modifications to the POD source and then regenerate the derived files.
For a quick introduction to POD, see the perlpod(1) man page on your
system (it should be installed if you have Perl installed).

When writing new documentation, write in whatever format you care to; if
necessary, we can always convert it to POD or whatever else we want to
use.  Having the documentation exist in I<some> form is more important
than what language you write it in.  If you really don't have any
particular preference, there's a slight preference currently for POD.

The pod2text and pod2man scripts that come with Perl versions prior to
5.6.0 are adequate but not ideal for processing INN's documentation.  The
best converters are available as part of the podlators package, available
from CPAN (ftp.perl.org or another mirror) in F<modules/by-module/Pod>;
fairly recent versions of the podlators utilities (and good enough for INN
documentation) come with Perl 5.6.0.  This module also requires
installation of PodParser for Perl versions before 5.6.0, found in the
same directory, and File::Spec for versions of Perl before 5.005.
File::Spec you can find in F<modules/by-module/File>.

To generate text documentation (like INSTALL or README), use:

    pod2text -s -l install.pod > ../../INSTALL

from the F<doc/pod> directory.  C<-s> preserves two spaces after periods
and C<-l> adds a blank line after major headings.

To generate a man page from POD source, use:

    pod2man -c "InterNetNews Documentation" -r "INN 2.3" in > out

where in is the name of the POD file and out is what to name the *roff
output.  For some documentation, you also have to provide -s <section> to
set the correct manual section (pod2man will assume section 1 if -s isn't
given).  It's best to run pod2man from the F<doc/pod> directory, directing
the output to the appropriate file in the F<doc/man> directory, since it
does some tricks with the name of the file to determine the title of the
man page and can be confused by longer paths.

At some point this should go into Makefile rules.

For conversion of POD to DocBook SGML, use Pod::DocBook, also found on
CPAN in F<modules/by-module/Pod>.

The current versions of these tools as of this writing are podlators 1.01,
PodParser 1.13, and Pod::DocBook 0.05.

=head1 Makefiles

All INN makefiles include Makefile.global at the top level, and only that
makefile is a configure substitution target.  This has the disadvantage
that configure's normal support for building in a tree outside of the
source tree doesn't work, but it has the significant advantage of making
configure run much faster and allowing one to run make in any subdirectory
and pick up all the definitions and settings from the top level
configuration.

The format of INN's makefiles have slowly been standardized; the best
examples of the current format are probably F<frontends/Makefile> and
F<backends/Makefile>, at least for directories with lots of separate
programs.  The ALL variable holds all the files that should be generated,
EXTRA those additional files that were generated by configure, SOURCES the
C source files for generating tag information, and INSTALLED the final
installed paths.

There are a set of standard installation commands defined in make
variables by Makefile.global, and these should be used for all file
installations.  See the comment blocks in Makefile.global.in for
information on what commands are available and when they should be used.
There are also variables set for each of the installation directories that
INN uses, for use in building the list of installed paths to files.

Each subdirectory makefile should have the targets all (the default),
clean, clobber, install, tags, and profiled.  The tags target generates vi
tags files, and the profiled target generates a profiling version of the
programs (although this hasn't been tested much recently).  These rules
should be present and empty in those directories where they don't apply.

Be sure to test compiling with both static and dynamic libraries and make
sure that all the libtool support works correctly.  All linking steps, and
the compile steps for all library source, should be done through
$(LIBTOOL) (which will be set to empty in Makefile.global if libtool
support isn't desired).

=head1 Scripts

INN comes with and installs a large number of different scripts, both
Bourne shell and Perl, and also comes with support for Tcl scripts
(although it doesn't come with any).  Shell variables containing both
configure-time information and configuration information from inn.conf are
set by the innshellvars support libraries, so the only system-specific
configuration that should have to be done is fixing the right path to the
interpretor and adding a line to load the appropriate innshellvars.

F<support/fixscript>, built by configure, does this.  It takes a .in file
and generates the final script (removing the .in) by fixing the path to
the interpretor on the first line and replacing the second line, whatever
it is, with code to load the innshellvars appropriate for that
interpretor.  (If invoked with -i, it just fixes the interpretor path.)

Scripts should use innshellvars (via fixscript) to get the right path and
the right variables whenever possible, rather than having configure
substitute values in them.  Any values needed at run-time should instead
be available from all of the different innshellvars.

See the existing scripts for examples of how this is done.

=head1 Include Files

Include files relevant to all of INN, or relevant to the two libraries
built as part of INN (the utility libinn library and the libstorage
library that contains all storage and overview functions) are found in the
include directory; other include files relevant only to a portion of INN
are found in the relevant directory.

Practically all INN source files will start with:

    #include "config.h"
    #include "clibrary.h"

The first picks up all defines generated by autoconf and is necessary for
types that may not be present on all systems (uid_t, pid_t, size_t,
int32_t, and the like).  It therefore should be included before any other
headers that use those types, as well as to get general configuration
information.

The second is portably equivalent to:

    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <string.h>
    #include <unistd.h>

except that it doesn't include headers that are missing on a given system,
replaces functions not found on the system with the INN equivalents,
provides macros that INN assumes are available but which weren't found,
and defines some additional portability things.  Even if this is more
headers than the source file actually needs, it's generally better to just
include F<clibrary.h> rather than trying to duplicate the autoconf-driven
hackery that it does to do things portably.  The primary exception is for
source files in lib that only define a single function and are used for
portability; those may want to include only F<config.h> so that they can
be easily used in other projects that use autoconf.  F<config.h> is a
fairly standard header name for this purpose.

F<clibrary.h> does also include F<config.h>, but it's somewhat poor form
to rely on this; it's better to explicitly list the header dependencies
for the benefit of someone else reading the code.

Another frequently included header file is F<macros.h>, which defines the
NEW(), COPY(), and DISPOSE() macros that are used throughout INN for
memory management rather than directly calling malloc(), strdup(), and
free().  (They actually use xmalloc() instead so you don't have to check
the return value, they include the file name and line number in error
messages resulting from out-of-memory conditions, and they make it easier
to plug in a debugging memory allocator when trying to track down memory
leaks or clobbers.)

F<paths.h> includes a wide variety of paths determined at configure time,
both default paths to various parts of INN and paths to programs.  Don't
just use the default paths, though, if they're also configurable in
F<inn.conf>; instead, call ReadInnConf() and use the global innconf
structure.

Other files in include, most notably F<libinn.h>, are interfaces to
particular bits of INN library functionality or are used for other
purposes; see the comments in each file.

Finally, many INN source files still include F<configdata.h>; this header
file is now obsolete (merged into F<config.h> and F<clibrary.h>) and
should be removed where it appears.

=head1 Coding Style

INN has quite a variety of coding styles intermixed.  As with all
programs, it's preferrable when making minor modifications to keep the
coding style of the code you're modifying.  In INN, that will vary by
file.

If you're writing a substantial new piece of code, the prevailing
"standard" INN coding style appears to be something like the following:

=over 3

=item *

Roughly BSD style (four space indents, no space before the parens around
function arguments, open brace on the same line as if/while/for, and close
and open brace on the same line as else).

=item *

Introductory comments for functions or files are generally written as:

    /*
    **  Introductory comment.
    */

Other multiline comments in the source are generally written as:

    /* This is a
       multiline comment. */

Comments before functions saying what they do are nice to have.  In
general, the RCS/CVS Id tag is on the first line of each source file.

=item *

Checks for NULL pointers are preferrably written out explicitly; in other
words, use:

    if (p != NULL)

rather than:

    if (p)

to make it clearer what the code is assuming.

=back

The source is currently full of some rather odd casts, including a lot of
casts to void when calling standard functions.  These are historical,
designed to make lint shut up.  Don't feel like you have to preserve them
provided that gcc -Wall doesn't complain when they're removed.

Note that this is only a rough guideline and the maintainers aren't style
nazis; we're more interested in your code contribution than in how you
write it.

Finally, if possible, please don't use tabs in source files, since they
can expand differently in different environments.  In particular, please
try not to use the mix of tabs and spaces that is the default in emacs.
If you use emacs to edit INN code, you may want to put:

    ; Use only spaces when indenting or centering, no tabs.
    (setq-default indent-tabs-mode nil)

in your ~/.emacs file.

=head1 References

Some additional references that may be hard to find and may be of use to
people working on INN:

=over 4

=item <http://www.mibsoftware.com/userkt/inn/dev/>

Forrest Cavalier provides several tools for following INN development at
this page and elsewhere in the Usenet RKT.  Under here is a web-accessible
checked-out copy of the current INN source tree and pointers to how to use
CVSup.

=item <http://www.sas.com/standards/large.file/>

The standards for large file support on Unix that are being generally
implemented by vendors.  INN sort of partially uses these, but a good full
audit of the code to check them should really be done and there are
occasional problems.

=back
