FreeBSD presently has a monolithic /etc/rc. A large number of people want to change this (and some people stay away from FreeBSD just because of this), but there is no clear plan forward. This document is an attempt at gathering different information about what is needed from such a system, provide reference information for the implementors, and collect the community's thoughts about it. It is presently written in a form which indicate me as author (first person) - I'll change this if I get any large contributions that make it inappropriate.


P.S. Thanks to David Wolfskill for picking parts of this to pieces and contributing more requirement points - you can do this too! ;-)


There are a bunch of different requirements and nice-to-have's - I suspect we can't satisfy all of them, but unless we actively detail them, each will only turn up as "hey! we can't do that!" when somebody present a scheme, and will keep us at the present system.

I'm presenting these in a somewhat random order, numbering them as I go. I may be doing subgroups etc later; the numbering is intended for somebody that attempt to make an implementation to have an easy way of referencing the requirements in their discussion/presentation of the scheme. This is not a prioritized list.

Available implementations

Useful concepts

I'm including a lot of stuff that probably is trivial to many of us. I want this to include enough background that somebody who doesn't know any of this can get my thoughts on it (by following the appropriate references if necessary).

Normalized representation vs de-normalized representation.

A normalized representation of something contains relevant information to construct the de-normalized version. In its correct form (where data is checked before using it), caching is storing both the normalized and the de-normalized version of something. Normalization / de-normalization is a question of viewpoint - a representation can be perfectly normalized from the point of view of one task, while being hopelessly de-normalized for another. The present task (starting services) is a great example. In order from less to more normalized:

  1. The monolithic /etc/rc scheme has de-normalized just about everything - all services are grouped together, a correct order is hard coded.
  2. The SysV scheme is somewhat less de-normalized - the services are split and their way of starting is normalized. The ordering is still de-normalized.
  3. A more normalized scheme would be to have each service provider say 'I need this service to run', 'I want to have this service, but I can work without it' and 'I want to run before that service'. This is perfectly normalized from the view of starting services.
  4. An even more normalized scheme would also track which variables a service used, so it could do things to the services depending on how variables changed.
The advantage of normalized representations is that they allow the system to do changes based on factors outside the constraints and usually allows people (or computers) to do changes to the data more easily - the disadvantage is that they are usually slower than using a de-normalized form if the result of the normalized system is to do the same as the de-normalized system. However, the extra information available from a normalized system often allow the computer to do something else that achieves the same result - for instance, a normalized representation of the rc files would allow parallel execution of different services.


You probably don't want to attempt to write a new rc system before you know what a graph is. You should know at least how to do a topological sort on an acyclic graph (described in any decent book on algorithms). This is not difficult to learn; it is just a couple of concepts you need to understand.

Event driven systems

It will be an advantage if you are used to thinking of event-driven system. The services can be viewed as variables in a dependency graph, with states 'on' and 'off' (and possibly others), and with variables also existing independently of services (example variable: the IP address of the default gateway).
However, you can also view the entire system as event or message-driven. In this case, switching the state of any variable create an event, and different parts of the configuration can wait for (subscribe to) different events. This has the nice side-effect of automatically doing the correct ordering (except for cycles) and making it reasonably easy to do (9), but makes it difficult to do (1), (10), (15) and probably (14) (unless we assume the parts of the system that need to run before switching the secure-level is run in a monolithic system, or create a couple of separate event systems).