1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
|
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.
First of all, if you plan on working on INN source, please start from
the current development tree. There may be significant changes from the
previous full release, so starting from development sources will make it
considerably easier to integrate your work. You can check out the
current development tree using Subversion from:
<http://inn.eyrie.org/svn/>
or view it with Trac source browser at:
<https://inn.eyrie.org/trac/browser/>
You will need autoconf 2.61 or later to use the development tree. After
checking out the tree, run "./autogen" to generate the necessary
autoconf files.
Nightly snapshots can be found at:
<ftp://ftp.isc.org/isc/inn/snapshots/>
Configuring and Portability
All INN code should be written expecting ANSI C and POSIX. There is no
need to attempt to support pre-ANSI compilers, and ANSI-only features
such as <stdarg.h>, string concatenation, "#elif", and token pasting may
be used freely. So far as possible, INN is written to attempt to be
portable to any system new enough that someone is likely to want to run
a news server on it, but whenever possible this portability should be
provided by checking for standard behavior in configure and supplying
replacements for standard functions that are missing.
When there is a conflict between ANSI C and C99, INN code should be
written expecting C99 and autoconf used to patch up the differences.
Try to avoid using "#ifdef" and the like in the middle of code as much
as possible. Instead, try to isolate the necessary portability bits and
include them in libinn or at least in conditional macros separate from
the code. Trying to read code littered with conditional compilation
directives is much more difficult.
The shell script configure at the top level of the source tree is
generated by autoconf from configure.ac and the additional macros in the
m4 directory, and include/config.h.in is generated by autoheader from
configure.ac. At configure time, configure generates 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 configure.ac.
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 "autoconf". To regenerate
include/config.h.in, run "autoheader". Alternately, to regenerate both,
you can run "./autogen". Please don't include patches to either
configure or include/config.h.in when sending patches to INN; instead,
note in your patch that those files must be regenerated. These (and all
other) generated files should not be checked into Subversion.
At the time of this writing, Autoconf 2.61 or later is required.
The supporting files for autoconf are in the support subdirectory,
including the files config.guess and config.sub to determine the system
name and ltmain.sh for libtool support. The latter file comes from the
libtool distribution available from
<http://www.gnu.org/software/libtool/>; the canonical version of the
former two are available from <ftp://ftp.gnu.org/gnu/config/> (which
currently redirects to
<http://git.savannah.gnu.org/gitweb/?p=config.git;a=tree>). In
addition, m4/libtool.m4 is just a copy of libtool.m4 from the libtool
distribution. (Using libtool without using automake requires a few odd
hacks.) New versions should be checked in periodically when available.
There are no INN-specific modifications to those files except for
ltmain.sh which recognizes the additional -B flag that INN's install-sh
script uses. This script should also be updated at the same time from
<http://git.savannah.gnu.org/gitweb/?p=automake.git;a=tree;f=lib>; it
similarly contains local modifications in order to support the
additional -B flag, as well as a few other changes mentioned in a
comment at the beginning of the file.
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.
Documentation
INN's documentation is currently somewhat in a state of flux. Much of
the documentation 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 doc/pod. The canonical source for most of
the text documentation, including README, INSTALL, NEWS, and this file,
is also POD.
If you're modifying some part of INN's documentation and see that it has
a POD version in doc/pod, you should 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 *some* form is more important
than what language you write it in. If you don't have a preference,
however, we prefer new documentation to be in POD.
If you use POD or regenerate POD documentation, please install something
close to the latest versions of the POD processing utilities to avoid
changes to the documentation depending on who generated it last. You
can find the latest version on CPAN (ftp.perl.org or another mirror) in
modules/by-module/Pod. You'll need PodParser (for versions of Perl
before 5.6.1; 5.6.1 and later come with a recent enough version) and the
latest version of podlators. For versions of Perl earlier than 5.005,
you'll also need "File::Spec" in modules/by-module/File.
podlators 1.25 or later will build INN's documentation without
significant changes from the versions that are checked into the
repository.
There are makefile rules in doc/pod/Makefile to build all of the
documentation whose master form is POD; if you add additional
documentation, please add a rule there as well. Documentation should be
generated by cd'ing to doc/pod and typing "make file" where "file" is
the relative path to the documentation file. This will get all of the
various flags right for pod2text or pod2man.
Error Handling
INN has a set of generic error handling routines that should be used as
much as possible so that the same syntax can be used for reporting
errors everywhere in INN. The six basic functions are notice,
sysnotice, warn, syswarn, die, and sysdie; notice prints or logs an
informative message, warn prints or logs a warning, and die does the
same and then exits the current program. The sys* versions add a colon,
a space, and the value of strerror(errno) to the end of the message, and
should be used to report failing system calls.
All of the actual error reporting is done via error handlers, and a
program can register its own handlers in addition to or instead of the
default one. The default error handler (message_log_stderr) prints to
stderr, prepending the value of message_program_name if it's set to
something other than NULL. Several other error handlers are available,
particularly including ones that use syslog. See include/inn/messages.h
for all of the available options.
There is a different set of error handlers for notice/sysnotice,
warn/syswarn, and die/sysdie. To set them, make calls like:
message_handlers_warn(1, message_log_stderr);
message_handlers_die(2, message_log_stderr, message_log_syslog_err);
The first argument is the number of handlers, and the remaining
arguments are pointers to functions taking an int (the length of the
formatted message), a const char * (the format), a va_list (the
arguments), and an int that's 0 if warn or die was called and equal to
the value of errno if syswarn or sysdie was called. The length of the
formatted message is obtained by calling vsnprintf with the provided
format and arguments, and therefore is reliable to use as the size of a
buffer to malloc to hold the result of formatting the message provided
that vsnprintf is used to format it (warning: the system vsprintf may
produce more output under some circumstances, so always use vsnprintf).
The error handler can do anything it wishes; each error handler is
called in the sequence given. Error handlers shouldn't call warn or die
unless great caution is taken to prevent infinite recursion. Also be
aware that sysdie is called if malloc fails in xmalloc, so if the error
handler needs to allocate memory, it must not use xmalloc or a related
function to do so and it must not call die to report failure. The
default syslog handlers report memory allocation failure to stderr and
exit.
Finally, die and sysdie support an additional handler (the external
variable message_fatal_cleanup) that's called immediate before exiting,
takes no arguments, and returns an int which is used as the argument for
exit. It can do any necessary global cleanup, call abort instead to
generate a core dump or the like.
The advantage of using this system everywhere in INN is that library
code can use notice, warn, and die to report messages and errors, and
each calling program can set up the handlers as appropriate to make sure
the errors go to the right place. The default handler is fine for
interactive programs; for programs that run from interactive scripts,
adding something like:
message_program_name = "program";
to the beginning of main (where program is the name of the program) will
make it easier to figure out which program the script calls is failing.
For programs that may also be called non-interactively, like rnews, one
may want to set up handlers like:
message_handlers_notice(2, message_log_stdout, message_log_syslog_info);
message_handlers_warn(2, message_log_stderr, message_log_syslog_warning);
message_handlers_die(2, message_log_stderr, message_log_syslog_err);
Finally, for daemons and other non-interactive programs, one may want to
do:
message_handlers_notice(1, message_log_syslog_info);
message_handlers_warn(1, message_log_syslog_warning);
message_handlers_die(1, message_log_syslog_err);
to report errors only via syslog. (Note that if you use syslog error
handlers, the program should call openlog first thing to make sure they
are logged with the right facility.)
For historical reasons, error messages that are fatal to the news
subsystem are logged at the LOG_CRIT priority, and therefore die in innd
should use message_log_syslog_crit. This seems like priority inflation
and may change in the future to message_log_syslog_err.
Test Suite
The test suite for INN is located in the tests directory and is just
getting started. The test suite consists of a set of programs listed in
tests/TESTS and the scaffolding in the runtests program.
Adding new tests is very straightforward and very flexible. Just write
a program that tests some part of INN, put it in a directory under tests
named after the part of INN it's testing, and have it output first a
line containing the count of test cases in that file, and then for each
test a line saying "ok n" or "not ok n" where "n" is the test case
number. (If a test is skipped for some reason, such as a test of an
optional feature that wasn't compiled into INN, the test program should
output "ok n # skip".) Add any rules necessary to build the test to
tests/Makefile (note that for simplicity it doesn't recurse into
subdirectories) and make sure it creates an executable ending in .t.
Then add the name of the test to tests/TESTS, without the .t ending.
For C tests, you probably want to use the functions in libtest.c
(prototypes in libtest.h) to handle all of the output. For shell script
tests, see the existing tests for some helpful shell functions.
One naming convention: to distinguish more easily between for example
lib/error.c (the implementation) and tests/lib/error-t.c (the test
suite), we add -t to the end of the test file names. So
tests/lib/error-t.c is the source that compiles into an executable
tests/lib/error.t which is run by putting a line in tests/TESTS of just
"lib/error".
Note that tests don't have to be written in C; in fact, lib/xmalloc.t is
just a shell script (that calls a supporting C program). Tests can be
written in shell or Perl (but other languages should be avoided because
someone who wants to run the test suite may not have it) and just have
to follow the above output conventions.
Additions to the test suite, no matter how simple, are very welcome.
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.
All INN makefiles should also set "$(top)" to be the path to the top of
the build directory (usually relative). This path is used to find
various programs like fixscript and libtool so that the same macros (set
in Makefile.global) can be used all over INN.
The format of INN's makefiles is mostly standardized; the best examples
of the format are probably frontends/Makefile and 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, and "SOURCES" the C
source files for generating tag information.
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"/"distclean", "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). 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 "$(LIBCC)" and "$(LIBLD)" (which will be set as appropriate in
Makefile.global).
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 interpreter and adding a line to load the appropriate
innshellvars.
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 interpreter on the first line and replacing the second line,
whatever it is, with code to load the innshellvars appropriate for that
interpreter. (If invoked with -i, it just fixes the interpreter 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.
As for Perl, the "INN::Config" module has the same features as
innshellvars.pl (only kept for compatibility reasons with old scripts
not shipped with INN); however, it can be safely used with warnings on
in Perl scripts.
See the existing scripts for examples of how this is done.
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*, *uint32_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. It also includes inn/defines.h and
inn/options.h, which pick up additional support macros and compile-time
configuration.
The second is portably equivalent to:
#include <sys/types.h>
#include <stdarg.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 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 config.h so
that they can be easily used in other projects that use autoconf.
config.h is a fairly standard header name for this purpose.
clibrary.h does also include 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.
There are portable wrappers around several header files that have known
portability traps or that need some fixing up on some platforms. Look
in include/portable and familiarize yourself with them and use them
where appropriate.
Another frequently included header file is inn/libinn.h, which among
other things defines xmalloc(), xrealloc(), xstrdup(), and xcalloc(),
which are checked versions of the standard memory allocation routines
that terminate the program if the memory allocation fails. These should
generally always be used instead of the regular C versions.
inn/libinn.h also provides various other utility functions that are
frequently used.
inn/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 inn.conf; instead, call innconf_read() and use the global *innconf*
structure.
Other files in include are interfaces to particular bits of INN library
functionality or are used for other purposes; see the comments in each
file.
Eventually, the header files will be separated into installed header
files and uninstalled header files; the latter are those headers that
are used only for compiling INN and aren't useful for users of INN's
libraries (such as clibrary.h). All of the installed headers will live
in include/inn and be installed in a subdirectory named inn in the
configured include directory. This conversion is still in progress.
When writing header files, remember that C reserves all identifiers
beginning with two underscores and all identifiers beginning with an
underscore and a capital letter for the use of the implementation; don't
use any identifiers with names like that. Additionally, any identifier
beginning with an underscore and a lower-case letter is reserved in file
scope, which means that such identifiers can only be used by INN for the
name of structure members or function arguments in function prototypes.
Try to pay attention to the impact of a header file on the program
namespace, particularly for installed header files in include/inn. All
symbols defined by a header file should ideally begin with "INN_",
"inn_", or some other unique prefix indicating the subsystem that symbol
is part of, to avoid accidental conflicts with symbols defined by the
program that uses that header file.
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. (Over time we're trying to standardize on one coding style, so
changing the region you worked on to fit the general coding style is
also acceptable).
If you're writing a substantial new piece of code, the prevailing
"standard" INN coding style is the following:
* Write in regular ANSI C whenever possible. Use the normal ANSI and
POSIX constructs and use autoconf or portability wrappers to fix
things up beforehand so that the code itself can read like regular
ANSI or POSIX code. Code should be written so that it works as
expected on a modern platform and is fixed up with portability tricks
for older platforms, not the other way around. You may assume an
ANSI C compiler.
Try to use const wherever appropriate. Don't use register; modern
compilers will do as good of a job as you will in choosing what to
put into a register. Don't bother with restrict (at least yet).
* Use string handling functions that take counts for the size of the
buffer whenever possible. This means using snprintf in preference to
sprintf and using strlcpy and strlcat in preference to strcpy and
strcat. Also, use strlcpy and strlcat instead of strncpy and
strncat, as it is much easier to audit uses of the former than the
latter. strlcpy is like strncpy except that it always nul-terminates
and doesn't fill the rest of the buffer with nuls, making it more
efficient. strlcat is like strncat except that it always
nul-terminates and it takes the total size of the buffer as its third
argument rather than just the amount of space left. All of these
functions are guaranteed to be available; there are replacements in
lib for systems that don't have them.
If you have to use a string copying routine that doesn't
nul-terminate, use memcpy instead. Avoid introducing any uses of
strcpy, strcat, strncpy, or strncat so that we can use grep to find
dangerous usages and switch them to better functions.
* Avoid "#ifdef" and friends whenever possible. Particularly avoid
using them in the middle of code blocks. Try to hide all portability
preprocessor magic in header files or in portability code in lib.
When something just has to be done two completely different ways
depending on the platform or compile options or the like, try to
abstract that functionality out into a generic function and provide
two separate implementations using "#ifdef"; then the main code can
just call that function.
If you do have to use preprocessor defines, note that if you always
define them to either 0 or 1 (never use "#define" without a second
argument), you can use the preprocessor define in a regular if
statement rather than using "#if" or "#ifdef". Make use of this
instead of "#ifdef" when possible, since that way the compiler will
still syntax-check the other branch for you and it makes it far
easier to convert the code to use a run-time check if necessary.
(Unfortunately, this trick can't be used if one branch may call
functions unavailable on a particular platform.)
* Avoid uses of fixed-width buffers except in performance-critical
code, as it's harder to be sure that such code is correct and it
tends to be less flexible later on. If you need a reusable,
resizable memory buffer, one is provided in lib/buffer.c.
* Avoid uses of static variables whenever possible, particularly in
libraries, because it interferes with making the code re-entrant down
the road and makes it harder to follow what's going on. Similarly,
avoid using global variables whenever possible, and if they are
required, try to wrap them into structures that could later be
changed into arguments to the affected functions.
* Use a roughly BSD indentation style but with four-space indents.
This means no space before the parenthesis around function arguments,
open brace on the same line as if/while/for, and close and open brace
on the same line as else).
* 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/SVN "Id" tag is on the first line of each source
file since it's useful to know when a file was last modified.
* 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.
* It's better to always put the body of an "if" statement on a separate
line, even if it's only a single line. In other words, write:
if (p != NULL)
return p;
and not:
if (p != NULL) return p;
This is in part for a practical reason: some code coverage analysis
tools like purecov will count the second example above as a single
line and won't notice if the condition always evaluates the same way.
* Plain structs make perfectly reasonable abstract data types; it's not
necessary to typedef the struct to something else. Structs are
actually very useful for opaque data structures, since you can
predeclare them and then manipulate pointers to them without ever
having to know what the contents look like. Please try to avoid
typedefs except for function pointers or other extremely confusing
data types, or for data types where we really gain some significant
data abstraction from hiding the underlying data type. Also avoid
using the "_t" suffix for any type; all types ending in "_t" are
reserved by POSIX. For typedefs of function pointer types, a suffix
of "_func" usually works.
This style point is currently widely violated inside of INN itself;
INN originally made extensive use of typedefs.
* When noting something that should be improved later, add a comment
containing "FIXME:" so that one can easily grep for such comments.
INN's indentation style roughly corresponds to that produced by GNU
indent 2.2.6 with the following options:
-bad -bap -nsob -fca -lc78 -cd41 -cp1 -br -ce -cdw -cli0 -ss -npcs
-ncs -di1 -nbc -psl -brs -i4 -ci4 -lp -ts8 -nut -ip5 -lps -l78 -bbo
-hnl
Unfortunately, indent currently doesn't get everything right (it has
problems with spacing around struct pointer arguments in functions,
wants to put in a space between a dereference of a function pointer and
the arguments to the called function, misidentifies some macro calls as
being type declarations, and fouls up long but simple case statements).
It would be excellent if someday we could just run all of INN's code
through indent routinely to enforce a consistant coding style, but
indent isn't quite ready for that.
For users of emacs cc-mode, use the "bsd" style but with:
(setq c-basic-offset 4)
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.
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.
Making a Release
This is a checklist that INN maintainers should go through when
preparing a new release of INN.
1. Update the files shipped with INN, and that are maintained by
external projects.
* Make sure that support/config.guess, support/config.sub,
support/install-sh, support/ltmain.sh and libtool m4 files
(libtool.m4, ltoptions.m4, ltsugar.m4, ltversion.m4 and
lt~obsolete.m4) are the latest versions. See the instructions in
"Configuring and Portability" for details on how to update these
files.
* Make sure that the latest version of C TAP Harness is used for the
test suite. It is available from
<http://www.eyrie.org/~eagle/software/c-tap-harness/>. The file
runtests.c should be updated. libtest.c, libtest.h and libtest.sh
come from tap/basic.c, tap/basic.h and tap/libtap.sh respectively.
Parts specific to INN should be kept during an update (especially
sections relative to LIBTEST_NEW_FORMAT because the test suite has
not yet been updated to use the new format of C TAP Harness).
2. Make sure that samples/control.ctl and samples/nocem.ctl are in sync
with the master version at
<ftp://ftp.isc.org/pub/usenet/CONFIG/control.ctl> and
<http://rosalind.home.xs4all.nl/nocemreg/nocemreg.html>.
3. Update doc/pod/news.pod and regenerate NEWS. Be more detailed for a
minor release than for a major release. For a major release, also
add information on how to upgrade from the last major release,
including anything special to be aware of. (Minor releases
shouldn't require any special care when upgrading.)
4. Bump the revision number in doc/FAQ (subject 1.2) so that it could
be included in a final release. It should not be changed for a beta
or a release candidate.
5. If making a major release, branch the source tree by creating a new
directory under branches in Subversion named after the major
release. This branch will be used for minor releases based on that
major release and can be done a little while before the .0 release
of that major release.
svn copy -r ZZZZ -m "Branch Y.Y.0 release." file:///srv/svn/inn/trunk file:///srv/svn/inn/branches/Y.Y
Then, remove the first paragraph in doc/pod/readme.pod which deals
with development versions.
6. Check out a copy of the release branch. It's currently necessary to
run "autogen" and "configure" to generate Makefile.global. Then,
run "make warnings" to generate all necessary files. Afterwards,
run "make check-manifest". There shouldn't be any differences;
otherwise, fix the MANIFEST file.
7. Run "make release" for a final release, "support/mksnapshot BETA b1"
for the first beta version of a new release, or "support/mksnapshot
RC rc1" for the first release candidate version of a new release.
Note that you need to have a copy of svn2cl from
<http://arthurdejong.org/svn2cl/> to do this; at least version 0.7
is required. Start the ChangeLog at the time of the previous
release. (Eventually, the script will be smart enough to do this
for you.)
Check that the ChangeLog file is correct; otherwise, regenerate it
or manually edit it. Then run again "make release" or any other
command you used.
8. Generate an MD5 checksum of the release tarball.
md5sum inn-Y.Y.Y.tar.gz > inn-Y.Y.Y.tar.gz.md5
9. Generate a diff between this release and the previous release if
feasible (always for minor releases, possibly not a good idea due to
the length of the diff for major releases). You will need the tar
file of the previous release for the comparison.
diff -Nurp inn-X.X.X inn-Y.Y.Y > inn-X.X.X-Y.Y.Y.diff
gzip inn-X.X.X-Y.Y.Y.diff
10. Make the resulting tar file, along with its MD5 checksum and the
possible diff from the previous release, available for testing in
the testing directory on ftp.isc.org and announce its availability
on inn-workers. Install it on at least one system and make sure
that system runs fine for at least a few days. This is also a good
time to send out a draft of the release announcement to inn-workers
for proof-reading.
11. Move the release into the public area of the ftp site and update the
inn.tar.gz link. Also put the diff and the MD5 checksum on the ftp
site and update the inn.tar.gz.md5 link. Contact the ISC folks to
get the release PGP-signed and the ISC web site updated (the
relevant contact is "web-request" instead of "webmaster"). Update
the inn.tar.gz.asc link. Possibly move older releases off into the
OLD directory.
12. After the ISC web site has been updated with links towards the new
release, send an announce on inn-announce and in news.software.nntp
(with a possible crosspost to news.admin.announce).
13. Tag the checked-out tree that was used for generating the release
with a release tag by copying it to tags in Subversion.
svn copy -r ZZZZ -m "Tag Y.Y.Y release." file:///srv/svn/inn/branches/Y.Y file:///srv/svn/inn/tags/Y.Y.Y
14. Bump revision numbers to reflect the one of the following release,
especially in doc/pod/install.pod and doc/pod/readme.pod for major
releases, configure.ac and Makefile.global.in for both minor and
major releases. The release versions in the Trac wiki should also
be updated.
References
Some additional references that may be hard to find and may be of use to
people working on INN:
<http://www.eyrie.org/~eagle/nntp/>
The home page for the IETF NNTP standardization effort, including
links to the IETF NNTP working group archives and copies of the
latest drafts of the new NNTP standard. The old archived mailing
list traffic contains a lot of interesting discussion of why NNTP is
the way it is.
<http://www.imc.org/ietf-usefor/>
The archives for the USEFOR IETF working group, the working group
for the RFC 1036 replacement (the format of Usenet articles), now
published as RFC 5536 and RFC 5537. Also contains a lot of
references to other relevant work. Another useful link is
<http://www.eyrie.org/~eagle/usefor/>.
<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. However, please note that
INN development now uses Subversion.
<http://tools.ietf.org/html/draft-lutchann-ipv6-intro-00>
A primer on IPv6 with pointers to the appropriate places for more
technical details as needed, useful when working on IPv6 support in
INN.
$Id: hacking.pod 9574 2013-11-26 19:08:41Z iulius $
|