User Tools

Site Tools


Table of Contents

Introducing the Sausalito Architecture


Cobalt completed its first Web server appliance software architecture in 1998 and began delivery of “Qube” and “RaQ” server products that same year. In two short years, the Web appliance market has taken off. Today, RaQ servers host hundreds of thousands of web sites in data centers around the world. Qubes provide basic web services for thousands more small businesses and educational institutions.

Software developers and service providers now view the Web as the medium for delivering services. They increasingly see Web server appliances as the vehicle for cost effectively and easily delivering these services to the edge of their customers’ networks.

As appliances, these products are fundamentally more cost effective and easier to use than pre-Internet general-purpose servers. Just as most consumers receive television entertainment through set-top box appliances on the edge of cable networks, millions of businesses, previously excluded from the information technology market place, will receive services through Web-enabled appliances attached to the Internet.

Cobalt recognized from the start that the user interface and underlying software architecture for these Web appliances must be designed specifically for this task. Cobalt has worked with leading network providers, including several of the world s leading ISPs and network service providers, to appliantize their Web services. Their requirements are at the center of Cobalt’s second-generation software architecture, named Sausalito, which is described in this developer guide.

Sausalito is specifically designed for delivery of services through the web model. This model allows services, hosted on the appliance, to deliver content to many users simultaneously through a graphical user interface.

Sausalito is designed to provide a superb developer platform, with the following goals in mind.

  • Provide an extensible architecture enabling third-party developers to customize, modularize, and implement services quickly. Sausalito interfaces are documented in this guide, including tools for tuning the user interface and interfacing with the built-in configuration database. The user interface also includes such features as a software update indicator and single-button install and delete capabilities.
  • Provide an easy to understand environment for non-technical users. Sausalito masks the complexity of its underlying software and is intended to provide the framework for maintenance-free services.
  • Use open standards for quick development time and strong security. Sausalito is designed to run on top of Linux and, in addition to its own interfaces, uses a number of standard services and interfaces like Apache and LDAP.
  • Provide flexibility to localize User interfaces into multiple languages quickly. Sausalito includes a language library for all localized data.


The audience for this document includes developers who create hardware or software applications that run on Sausalito, Value Added Resellers, and others who want to customize Sausalito-based systems to fit their requirements.

About This Book

This book contains the following sections:

  • Chapter 2, About The Sausalito Architecture, provides a high-level tutorial of the components that make up Sausalito.
  • Chapter 3, User Interface, explains how the User Interface works with code samples and examples of how to change the style.
  • Chapter 5, Introducing The Cobalt Configuration Engine describes the interaction between the underlying software for Sausalito.
  • Chapter 6, Making Sausalito-Aware Applications, describes the file structure you must use to create an application that runs on the Qube 3.
  • Appendix A, User Interface Foundation Classes lists the methods in the User Interface Foundation Classes (UIFC).
  • Appendix B, Utility Classes lists the methods for the Utility Classes.
  • Appendix C, , Appendix C, About Style, lists the default styles used in Sausalito.
  • Appendix D, Base Data Types lists the base data types used in Sausalito. You should be aware of these data types so that your software does not overwrite them.
  • Appendix E, Cobalt System Configuration Protocol describes the CSCP protocol.
  • Appendix F, CCE Class Definitions lists the properties of CCE classes.

NOTE: This draft includes a subset of the set of final chapters and appendices that will be available when complete. It is being made available in its beta form to help third-party developers create applications.

no longer available
For information on using Sausalito, please see the Qube 3 User s Guide, which is available at Information about Sausalito will also available at

Document Roadmap

This roadmap tells you where to find information for specific tasks.

TaskWhere to find information
Adding a new menu itemAdding a New Navigation Node on page 3—6
Changing the logoMaking Other Style Changes on page 3—11
Changing the background colorChanging the User Interface Style on page 3—10
Internationalizing your applicationUsing i18n and l10n in Sausalito on page 4—1
Adding a new serviceBuilding a New Service Module on page 6—3
Working with the Object Database (ODB)Appendix D
Working with the UIFC classesAppendix A
Working with the Utility classesAppendix B
CSCP LibrariesAppendix E
What are the base classes for SausalitoAppendix C
What are the CCE class definitionsAppendix F

Conventions Used in this Guide

Typographical Conventions

Bold is used for emphasis, for example:

  • Each UIFC page should have one and only one page object.

Bold is also used for words found in the user interface, for example:

  • test.xml is shown adjacent to Style.

Italic font is used for variables, for example:

  • require ::= string

Italic font is also used for new terms when they are first used, for example,

  • these widgets are manipulated from a PHP script by the developer.

Subscript is used for program names and code. for example:
CCE Auth command returns NULL for failure or a session key for success.
char *cce_auth_cmnd

Larger blocks of code will be highlighted using the GeSHi Generic Syntax Highlighter

 * The HelloWorldApp class implements an application that
 * simply displays "Hello World!" to the standard output.
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); //Display the string.

Programmatic Conventions

The class definitions use the following conventions:

  • All class names have the first character capitalized. For example, System. If they have more than one word, the first character of all words is capitalized. For example, MailList.
  • Namespace names follow the same rule as class names.
  • All property names start with an all lowercase first word. If a property name has more than one word, the first characters of the second word onwards are capitalized. For example, gateway and stylePreference are valid property names.


Sausalito has its own unique terminology:

Cobalt Configuration Engine (CCE):A general name for the entire configuration architecture.
Cobalt System Configuration Protocol (CSCP):The protocol which connects the CCE client to the session manager and the Cobalt Object database. CSCP connections provide object-database functionality and executes handlers as necessary.
Event:A change in a property of a object within the database.
Client:A program using CSCP to request or change information.
Handler:A program called by CCE to affect an event.
Cobalt Configuration Engine daemon (cced):The server process which handles incoming connections and signals.

About the Sausalito Architecture

This chapter provides a tutorial-style overview of the Sausalito architecture. It describes the basic concepts, the issues that were addressed in creating this appliance architecture, and the solutions that were implemented to address them.

The Appliance Concept

When designing software for a general purpose server, the designers must put as few restrictions on flexibility as possible. However, an appliance does not have this restriction. A Cobalt appliance is designed with a single goal in mind: providing a full range of services through a single user interface, while keeping the ease of use of household appliances. This goal enables us to narrow the scope of the software, and consequentially tightly integrate the software into the system.

The Sausalito software architecture is an answer to the appliance concept. Sausalito allows Cobalt to provide a single back-end mechanism for monitoring and manipulating the system software. Through this mechanism, a very simple user interface can operate, while keeping the details of the backend system logically separate.

This separation of interface and implementation is a cornerstone of reusable and reliable software design. This allows developers to have a stable exported interface that can be used in their applications for complete integration into the Cobalt environment. This is one of the major goals of Sausalito.

Figure 2—1 provides a basic view of Sausalito architecture. The interface provides the glue between the user interface and back end.

FIXME: Figure 2-1 Overview of Sausalito

The User Interface Defines the Appliance

Appliances make complex systems very easy to use. The user interface plays a strong role in defining the appliance. Sausalito provides the foundation to build web-based user interface on the user interface layer. This layer communicates with users and routes information to and from the back-end. There are several components in the this layer: the navigation manager, User Interface Foundation Classes (UIFC) and stylist.

Sausalito was designed to meet internationalization requirements. Sausalito supports users at different locales by working with European and Asian languages. The user interface layer uses a internationalization library to handle this requirement. For example, when the user interface needs to display Welcome to users who speaks German, it asks the internationalization library to get the translated string Willkommen to display to users.

The navigation manager component is designed to provide basic navigation capabilities to user interfaces. The idea is to separate data that defines the site map and the navigation managers that walk through the map. On a site map, each node denotes a page on the user interface and each page can have multiple widgets. Information about the nodes are stored in special files.

Given a site map, it is up to navigation managers to determine how to walk through them. Different navigation managers can walk through the same site map differently. Some navigation manager can provide a step-by-step walk through while other can show the whole map as a tree structure so that users can pick the right node instantly.

Building Pages

Sausalito provides many utility libraries and UIFC as a widget set on which you can build user interface pages. One of the goals of UIFC is to provide consistency among different pages on a user interface. This is extremely important for the interface s ease of use. For example, UIFC, fields that represent boolean selections always look the same. Otherwise, boolean selections can be represented as a checkbox, two radio buttons or a change-state- button.

UIFC is object-oriented. Each widgets have their corresponding classes. Also, UIFC is currently implemented in PHP. Developers must have a basic understanding of object- oriented programming and PHP before examining UIFC. PHP is a very easy-to-learn and versatile scripting language designed to build web pages.

HtmlComponentFactory is a UIFC class that construct widgets and talk to the internationalization library. The basic task of this class is to instantiate UIFC widget classes in common ways and give them parameters of the desired locale. This is the first class to understand within UIFC.

ServerScriptHelper is a utility class that simplifies page building. Its main job is to communicate with CCE for authentication and for getting user preferences. It also provides methods to make page building easy.

User Interface with Style

There are lots of style properties on an user interface. A web user interface includes fonts, font size, color, images, alignment, and other properties. UIFC support style properties, which are stored in special files. UIFC widgets parses through these files to get the right style to display. Sausalito allows multiple styles coexist on the system and allows users to choose ones they prefer. Styles are pretty much like skins in some applications.

Built-in Internationalization

Internationalization is built into Sausalito and supported through an internationalization library. Sausalito users often refer strings by their references rather than the actual strings.

This way, the actual string can be fetched from the string catalog based on the locale preference of the user who read the string. Sausalito users can also set locale-specific properties. For example, when an input field should only be displayed for Japanese but not for other languages, we can introduce a inputField property and set it to true only for Japanese.

Of course, the code that manages this field must be made aware of this property. Sausalito is designed such that objects representation resides only on the user interface layer. Developers should not be surprised that anything below the user interface layer only passes references instead of the actual strings or other locale-sensitive resources. When the user interface gets the reference and decides to use it, the internationalization library is then called to resolve it.

Abstraction of the System into Objects

The first step towards separating the interface from the implementation is to separate the data from the process. System data, such as configuration options and users, can become abstract groupings of data or objects. These objects are self-contained, dictating only the information necessary to recreate themselves. An application can define a class or data structure to enable the system to know about and manipulate its data.

This provides developers a flexible way to define new configuration items to the system, as well as a convenient and single mechanism by which to read all system configuration data.

FIXME: Figure 2—2 shows the addition of classes and objects.

Storing the Objects

Once we have well-defined objects that can accurately represent the system, we need to define how and where to store them and how to retrieve and modify them. Unlike reading configuration files, such as /etc/passwd or httpd.conf, to determine the state of the system, a good abstraction should provide a single, flexible way to access all system configuration data.

The Cobalt Object Database (CODB) is provided as a place to store objects. It is not a database in the sense of commercial relational databases designed to run a corporate enterprise, but instead store the known state of the system. CODB acts as a buffer between a user interface and the system itself.

Objects can be stored, retrieved, modified, and destroyed, all without the user interface having to know about the details of any given application configuration mechanism. Figure 2—3 adds the Cobalt Object Database (CODB).


Manipulating the Objects

Now that we have objects that can be stored, created and destroyed, we need to define a mechanism by which to do these things. In order to provide a manageable and accountable access method, Cobalt has defined the Cobalt System Configuration Protocol (CSCP), which connects clients to the Cobalt Configuration Engine (CCE). CCE is the process that implements CODB.

CSCP provides primitives to read, write, create, destroy, and search for objects. To make accessing CSCP easier, Cobalt provides libraries in several common programming languages, such as C, Perl and PHP.

FIXME: Figure 2-4 Connecting the UI to CCE and CODB

Extending the Objects

Now that application packages can export their configuration data via CODB classes, other software packages can take advantage of this. Many times, an application package adds some functionality to an existing object that didn’t exist in the base object. Consider an application that provides some per-user configuration options. With CODB classes, it is easy to define a class for this data. Now the UI can create an object of this class (an instance) whenever a user is created, and destroying the instance whenever a user is destroyed.

There is one more problem, however. A good abstraction of the object knows nothing of the user interface, and a good user interface engine knows nothing of what classes are available. How, then, do we associate this new per-user class with a user object?

CODB provides the ability to extend a class with a namespace. A namespace is a set of properties, like a class, that piggy-backs onto other classes. We can change our per-user class into a user namespace. Now, whenever a user gets created or destroyed, the namespace goes with it. We also solve the issue of association. We know our new namespace is associated with user objects by it’s namespace association.

Watching for Changes

At this point, we have the Cobalt Configuration Engine (CCE) running a database (CODB) which stores instances of classes and namespaces. This configuration engine understands the CSCP protocol to affect changes on the CODB. How do the changes made to the CODB become changes made to the system?

Application packages can register via configuration files to be notified when certain events occur. The registration mechanism provides the ability for any software package to register event handlers (or just handlers) on any class or namespace known to the system. Events understood by the CODB are create events, destroy events, and modify events.

Now that we can register handlers, our software package can create a handler for any events about which it is concerned. For example, if we need to add a user to our application s access list, we might register on the user-create event. When a user is created, our handler is invoked, and we can do our specific task.

Actuating the Changes

When an event is triggered, CCE steps through the list of handlers for that event, and runs each of them, in turn, until one fails, or there are no more handlers to run. It is the responsibility of each handler to make the appropriate changes to the system configuration to actuate the event.

FIXME: Figure 2-5 - Making changes to the system

Modularity — Doing Your Own Thing

At every stage of Sausalito, concern has been given to retain modularity. It is the goal of the architecture to make adding and removing software packages have no impact on the rest of the system. This principle should be adhered to as much as possible.

What CCE is Not

CCE is not a generic data-store. It is not a place for applications to store their data. It is meant to be a buffer between making abstract changes in the configuration of the system, and those changes happening on the system.

CCE is not a place to store user-interface definitions. CCE should know as little as possible about any particular user interface implementation.

User Interface

Sausalito is Cobalt's first fully open programming interface. It is designed to enable third-party developers to create applications that are seamlessly integrated into the look and feel of Sausalito-based appliances. One of the layers within Sausalito is the user interface, which enables you to:

  • Manipulate navigation with navigation managers and site maps
  • Manipulate look-and-feel style
  • Build user interfaces pages that are consistent with Sausalito-based systems

How the Navigation System Works

The navigation system is a sub-system within the user interface that manages navigation through site maps. The system consist of site maps and navigation managers.

The navigation system on Sausalito is a dynamic system. It is generated from a set of files that define navigation nodes. By linking these nodes together, a site map is formed. Users can construct site maps by adding and removing nodes. These site maps are then interpreted by navigation managers. Whenever a user logs in to the user interface, navigation managers use the site map to govern how the user navigates.

Each node on the navigation graph is defined in a XML file. You must have a basic understanding of how XML works to use navigation; for XML information, see

Navigation node XML files are located under /usr/sausalito/ui/menu directory. These files are very simple. It does not matter where or in what subdirectories these files are placed.

All graph related information are contained within the files. Directories can be used to group these files into a more maintainable manner. To add a node, create a new XML file under the directory. To remove a node, remove the file. Each XML file contains all the information the navigation system needs to know about a node.

XML Elements

There are three elements navigation node XML files can use. They are item, parent, and access elements. Each of the files must contain one and only one item element. Each item element contains zero to many parent elements. The parent elements can be viewed as links from the children to the parent node. A collection of nodes and links together composes a site map. Each parent element can have zero or more access elements.

With no access element, the parent link has no access control and anybody can traverse the link. With one access element, access is granted if and only if this requirement is met. With more than one access element, access is granted if any one of the multiple requirements are met; this is a OR condition.

id[a-zA-Z0-9_\-]+id must be unique among XML files. Therefore, it is advisable to prepend package or vendor tag to the id. See Using Unique Names on FIXME page 3—6
labelinternationalizable stringlabel is a short readable string that labels the node. Navigation managers can display a list of labels for users to navigate to. The interpolate function of I18n module is used to internationalize this string.
descriptioninternationalizable stringLabels can sometimes be too short. A description is used complement the label in describing the node s content. The interpolate function of I18n module is used to internationalize this string.
typestringtype is used by navigation managers to distinguish items. They can then act on the items differently. Optional.
urlURL as described in RFC 1738, internationalizableThis url points to the content page of this node. The interpolate function of I18n module is used to internationalize this string. Optional.
Table 3—3 Parent Elements Attributes
orderintegerWhen there are several children nodes under a parent node, the navigation managers might need to know which child to use first. The smaller the integer, the more important the node is. Optional.
requirestringThis is the access required to traverse the parent link. Optional.
Table 3—4 Access Elements Attribute
requirestringThis is the access required to traverse the parent link.

There are three navigation managers supported by the system currently. They are collapsible list navigation, flow navigation and single navigation. New navigation managers maybe added in the future.

Here is an example site map here to illustrate how navigation managers work:

  • Node A has no parent
  • Node B’s parent is A
  • Node C’s parent is A
  • Node D’s parent is C and E
  • Node E has no parent
  • Node F has no parent
  • Node G’s parent is F
  • Node H’s parent is G
  • Node I’s parent is G and J
  • Node J has no parent

The site map looks like Figure 3—1

FIXME Figure 3—1 Site Map

The collapsible list navigation manager presents a site map in a collapsible list format and lets users navigate by clicking on items on the list. Users can expand or collapse parents to show and hide the children nodes, respectively.

To use the collapsible list, users needs to supply the root node of the site. For example, using the above site map as an example with A as root, the collapsible list will look like:

FIXME Check this…




Note that the node A and E are not being shown. This is because node A is the root and there is no path to descend down from the root to node E. The nodes F, G, H, I and J are not shown either because they are on a separate branch.

The URL for collapsible list navigation manager is at /nav/cList.php. It needs a root parameter that specifies the id of the root. Therefore, use it like http://<ip>/nav/cList.php?root=<root>.

The flow navigation manager allows users to navigate forward or backward through a site map. Conditional branches for forward are supported.

The root node needs to be supplied to the flow navigation manager and that becomes the first step of the flow.

Take the above site map as an example with F as the root. Navigation starts at F. Users can move forward to G. No moving backward is allowed on the root node. At G, users can move backward to F or forward to either H or I. Moving to H or I depends on a condition check at G. At H or I, users can move back to G or finish the navigation. Note that users at I cannot move backward to J.

Conditional forward is supported by a JavaScript interface. At the node where a conditional forward is necessary, that is, G in the above example, a getNextItemId()JavaScript function must be specified in the content page. This function should return the id of the next node when it is called with no parameters.

Error checking is supported. When an user wants to move forward, all the submitHandler()s of all the form elements of the content page are called with no parameters. The forward operation proceeds only if all the submitHandler()s return true. If you use UIFC to build your content page, submitHandler()s are automatically defined.

During the forward operation, after error checking is done at the front end, the form on the content page is submitted. The handler of the form submit should tell flow navigation manager if submission is successful or not. If successful, navigation moves to the next node.

Otherwise, it stays at the same node. To notify the navigation manager, the form handler should return a page which sets the JavaScript variable flow_success to true or false, with true indicating success. Note that this variable is automatically handled by the toHandlerHtml() method of the ServerScriptHelper class.

The URL for flow navigation manager is at /nav/flow.php. The root parameter needs to be supplied, so use something like http:<ip>/nav/flow.php?root=<root>. Single navigation manager only supports one single node and does not allow users to navigate into other nodes. The URL for single navigation manager is at /nav/single.php. The root parameter needs to be supplied, so use something like http:<ip>/nav/single.php?root=<root>.

Adding a New Navigation Node

The example below demonstrates how to add nodes to the User Interface (UI). We will add two nodes in the example. Figure 3—2 on page 3—9 shows the result of this addition.


    label="Hello World App"
    description="This menu contains the Hello World application">
  <parent id="base_administration" order="100"/>


    description="This item says hello to the world"
  <parent id="sample_helloworldmenu" order="0"/>

Node sample_helloworldmenu is a child to node base_administration and node sample_helloworld is a child of node sample_helloworldmenu.

Using Unique Names

You must use unique names for navigation nodes to avoid name conflicts. Cobalt recommends that you choose a vendor-specific name for your modules, and create directories with the vendor name. For example, if your company name was ivory, your XML files for the account information page would be ivory_account.xml in the /usr/sausalito/ui/ menu/ivory directory.

Building Pages

Pages on Sausalito are built with PHP, because UIFC, the widget classes, and other utility classes are currently implemented in this language. These classes the foundation of Sausalito user interfaces and they are available to be used by developers.

NOTE: More information on building pages will be included in future drafts.

The object classes, called the UIFC define objects such as buttons, lists, checkboxes, and radio buttons. These widgets are manipulated from a PHP script by the developer, and then are automatically turned into proper HTML for display to the user. All the UIFC widgets have been built with the concept of styles. This allows the look of the entire UI to change, with no code changes. UIFC has also been designed to work seamlessly with internationalization, commonly referred to as i18n. See Appendix A for a complete reference for UIFC.

NOTE: See Chapter 4 for information on internationalization. The utility functions provide pre-packaged functionality that is commonly needed by web- based UIFC applications. Utilities, such as conversions between strings and hashes, and widget allocations are greatly simplified by utility functions. See Appendix B for a description of the utility classes. For information on Styles, see The User Interface Style on page 3—9.

A Further Example

We’ve already shown some examples of adding a menu, so let’s put all the pieces together and see how it looks. This example will be expanded in subsequent chapters to show how to internationalize your application, add handlers, and have it work with Sausalito s Active Monitor.

    label="Hello World App"
    description="This menu contains the Hello World application">
  <parent id="base_administration" order="100"/>
    description="This item says hello to the world"
  <parent id="sample_helloworldmenu" order="0"/>


<body bgcolor="#ffffff">
<h1> Hello, World! </h1>

Putting all of these files together creates the web page shown in Figure 3—2 on FIXME page 3—9.Now, we can take advantage of the UI libraries. It might seem odd that the next example is, in fact, longer than the non-UIFC version, but for a use as trivial as this, the overhead of UIFC outweighs the benefits. When pages get longer and more complex, however, the benefits dwarf any overhead.


/* PHP file to display "Hello, World" */
$servhelp = new ServerScriptHelper();
$factory = $servhelp->getHtmlComponentFactory("base-am");
$page = $factory->getPage();
$label = $factory->getLabel("Hello, World!", false);

Putting all these files into place results in the screen shown in Figure 3—2.

FIXME Figure 3—2 Hello World in the Cobalt Menu

The User Interface Style

How Styles Work

The UI styles are defined in Style definition files. The Style definition file contains all the configurable items of the look and feel of UIFC s visual appearance. You can modify this file to change logos, background colors, text, and other features. See FIXME Appendix C, About Style.

Changing the User Interface Style

Style interacts with the UIFC that are described in Appendix A. Most of the widgets depend on Style to set background images and colors, font size and weight, and other parts of the visual elements.

Sausalito ships with one style file: trueBlue.xml. You can modify this file and save it as your own style file. You must give it a new name and create a new directory for your own style. The following example gives you high level instructions for creating a directory for your new style sheet, copying and modifying the style file.

IMPORTANT! You must make a copy of trueBlue.xml.

  1. Change directories to /usr/sausalito/ui/style.
  2. Copy the style file, trueBlue.xml, to vendor_style.xml.
  3. Add any graphics or other files needed for your style file.

The following is an example of modifying the trueBlue.xml file. In this example, the following UI properties were changed, as shown in FIXME Figure 3—3 on FIXME page 3—11.

  • trueBlue.xml was copied to test.xml; the word test is shown adjacent to Style in Figure 3—3 on page 3—11.
  • The color value for the aLinkColor value was changed to #0033CC.
  • The title alignment was changes from left to right by modifying the tabAlign value.
  • The font size was changed by modifying <property name=“fontSize” value=“12pt”/> to <property name=“fontSize” value=“18pt”/>.

Similarly, changes were made to the background and divider colors of the table cells, and to the button font and colors, and to the alignment of the image.

Below is an example of a modified style file.

FIXME Figure 3—3 Modified Style File

Making Other Style Changes

You can make other style changes in addition to the ones shown in FIXME Figure 3—3 by making further modifications to your vendor_style file.
You can substitute your logo for Cobalt's logo by searching for the line:

<property name="logo" value="/libImage/topLogo.gif"/>

and putting the .gif file for your logo in place of topLogo.gif.

Using I18n and I10n in Sausalito

i18N: A World Tour

This chapter explains how to internationalize and localize Sausalito.


This chapter uses two terms: internationalization, which is referred to as i18n, and localization, which is referred to as l10n.

Internationalization (i18n)

Internationalization refers to the operation by which a set of programs are made aware of and are able to support multiple languages. This is a generalization process by which the programs are untied from calling only strings of a locale or other locale-specific habits, instead of connected to generic ways of doing the same. Program developers can use various techniques to internationalize their programs. GNU gettext offers one of these standards. For more information about gettext, see

Localization (l10n)

Localization means the operation by which, in a set of programs already internationalized, the developer gives the program all needed information so that it can adapt itself to handle its input and output in a fashion that is correct for some native language and cultural habits. This is a particularisation process, by which language and cultural habits. This is a particularisation process, by which generic methods already implemented in an internationalized program are used in specific ways. The programming environment puts several functions to the programmers disposal which allow this runtime configuration. The formal description of specific set of cultural habits for some country, together with all associated translations targeted to the same native language, is called the locale for this language or country. Users achieve localization of programs by setting proper values to special environment variables, prior to executing those programs, identifying which locale should be used.

How Internationalization Works

The Sausalito architecture provides a simple-to-use interface to a database of localized strings used for internationalizing applications. This i18N interface is similar to the GNU gettext interface, and is, in fact, a higher-level wrapper than encapsulates GNU gettext functionality.

Like GNU gettext, the Sausalito i18n library allows developers to create their own databases of localized strings, and provides an interface for accessing that database from within applications. The Sausalito i18n wrapper library adds the following new functionality:

  • Strings fetched from the library are subject to an interpolation process, in which usersupplied variables and even other internationalized strings can be automatically substituted into the localized string.
  • Access to a set of routines for properly escaping the fetched strings for use in web applications, that is, for use in HTML documents or JavaScript programs.
  • Automatic negotiation of the best possible locale, from a preference-ordered list of locales.

Using Domains, Tags, and Locales

The Sausalito i18N library manages a database of localized strings. Each application or module is granted it’s own namespace within the database. This namespace is a called a domain. Within each domain, individual messages are identified a string known as the message tag.

When an application retrieves a message from the i18N database based on the message’s domain and message tag, the i18n searches the database for a localized message that most closely matches the preferred locale.


A domain is a grouping for a similar set of resources, for example, the sendmail package can be a unique domain. In practical terms, localization strings are packaged by domain. Each domain defines the default language for its use in its own prop file. This file contains only a locale specification. The file is located in the same directory and locale property files except that its name is derived from the domain rather than the locale, for example, cobalt.prop for the Cobalt domain.

Developers retrieve message strings from the i18N database by specifying both the domain and the message identifier for each string.


A tag identifies a text string within a domain of strings for used in interpolation and I18N. The tag identifies the localized string. The localized string is identified by the tag specified in the function call and the domain specified within the i18N object. The locale used is the one negotiated during the creation of the i18N object. Developers retrieve message strings from the i18N database by specifying both the domain and the message id for each string using the “domain.msgid” tags.


Locales are specified by strings that start with an ISO-639 two-letter language code and an optional variant, all separated by underscore characters, for example, en_US.

In summary, the grammar for a locale identifier is:

locale_id := lang-code [ ’_’ country-code [ ’_’ variant-code ] ]

where lang-code, country-code, and variant-code are all alphanumeric codes defined in ISO-639.

Following are some example locale identifiers:

  • en: Generic english
  • en_US: English, American dialect
  • ja_JP_EUC: Japanese, as spoken in Japan, the EUC variant

When the i18n library is initialized by an application, a comma-delimited list of locales is supplied to the i18n library. This list of locales indicates the various locales that the user can understand, in order of preference. The i18n library uses an intelligent algorithm to attempt to select the best available locale for each domain because not all domains support the same set of locales, for example: en_US or en, ja.

How Strings Are Added to the System

Adding new strings to the system in a three-step process:

  1. A new .po file is created. This .po file defined all the message strings for one domain and one locale.
  2. The .po file is compiled into an .mo file using the msgfmt tool.
  3. The .mo file is placed in the appropriate directory beneath /usr/share/locale/locale/LC_MESSAGES.

Using Interpolation

When a string is fetched from the i18n library, it is subject to a process called interpolation. Interpolation allows user-supplied variables to be intelligently substituted into the string in various places. It also allows a string to contain references to other messages in the i18n database, with are expanded to full messages when interpolation occurs.

As a quick example, if the following string were stored in the i18n message string database:

"Hello, my name is [[]]."

The i18n_get function is called such that the user supplied variable name was set to Bob, the following string would be returned by the library:

"Hello, my name is Bob."

Interpolation Rules

Every time a localized string is retrieved from the I18N database, it undergoes interpolation according to the rules defined below.

Rule 1. The string is subdivided into a list of tokens according to the following grammar:

string := token*
token := ( text | tag )
tag := [[ domain . tagname var* ]]
var := , key = value.
text := escaped-string
domain := escaped-string
tagname := escaped-string
key := escaped-string
value := escaped-string

NOTE: The tag grammar interpolates the tag configuration in this format and substitutes variables into the string.

Rule 2. Strings are unescaped according to the following rules:

  • \n → newline
  • \b → backspace
  • \a
  • \f → formfeed
  • \n → newline
  • \r → return
  • \t → tab
  • \v → vertical newline
  • \(char) → literal character

Rule 3. Tags are subject to the following expansion rules:
If the domain equals VAR, then variable expansion occurs. The variable specified in tagname is looked up in the current hash of variables. Its value is interpolated according to these rules and its value is substituted here.

If the domain is not equal to VAR, than the domain token is interpreted as the name of a i18n domain. The tagname token is interpreted as a message identifier, and the appropriate substring is fetched from the i18n database and interpolated.

Rule 4. The expanded unescaped tokens are reassembled into a single internationalized string.

The i18n Interface

Application developers use the following interface to fetch properly interpolated and escaped strings from the i18n database. Generally, the programmer first calls a constructor to create a new i18n object, perform a number of fetch operations, and then destroy the i18n object.

The i18n object performs its own memory management on strings that it returns. When the i18n object is destroyed, all memory allocated for various strings is freed automatically.

The i18n library is a C library, but Perl and PHP bindings are provided in addition to the C interface. These various interfaces to the i18n library are documented below.

The i18n C Language Interface

The function prototypes for the C language interface are in the following include file:


The link library for i18n is in these directories:

/usr/sausalito/lib/libi18n.a (library for static linking)
/usr/sausalito/lib/ (library for dynamic linking)

The function interface for the C-language interface follows.

i18n_handle *i18n_new (char *domain, char *locales)
  • Summary: constructs a new i18n object, and returns a pointer to it.
  • Parameters
    • domain: identifies the default domain to use for operations where domain is omitted.
    • locales: a comma-delimited list of locale identifiers, listed in order of preference. This list of locales is used to choose the best locale for each domain when strings are retrieved from the database.
  • Returns: NULL for failure. Otherwise, returns a handle to a newly constructed i18N object.

void i18n_destroy (i18n_handle *handle)
  • Summary: destroys an i18n object, cleaning up all memory allocated by the i18n object.
  • Parameters
    • handle: the i18n object to be destroyed.
  • Returns: Nothing.

i18n_vars * i18n_vars_new ( void )
  • Summary: constructs a new object used to storing an associative array of variables for use by the various i18n interpolate and get functions.
  • Parameters
    • None
  • Returns: A pointer to a new i18n_vars object (a GHashTable).

void i18n_vars_add (i18n_vars *v, char *key, char *value)
  • Summary: adds a new key-value pair to the i18n_vars object. Copies of both the key and value are stored within the i18n_vars object. If this object is passed to a i18n_interpolate or similar function, it is used during interpolation to expand the VAR tags.
  • Parameters
    • v: a pointer to a valid i18n_vars object key – a null-terminated string indicating the variable name
    • value: a null-terminated string indicating the value of the named variable.
  • Returns: Nothing.

void i18n_vars_destroy (i18n_vars *v)
  • Summary: destroys an i18n_vars object, and frees all memory associated with it.
  • Parameters
    • v: the pointer to the i18n_vars object to destroy
  • Returns: Nothing.

char *i18n_interpolate (i18n_handle *h, char *str, i18n_vars *vars)
char *i18n_interpolate_html (i18n_handle *h, char *str, i18n_vars *vars)
char *i18n_interpolate_js (i18n_handle *h, char *str, i18n_vars *vars)
  • Summary: These three functions provide direct access to the interpolation functionality within the i18n library. The i18n_interpolate function does not escape it’s output at all. The i18n_interpolate_html function performs an additional escaping expansion on the string it returns, escaping it appropriately for use in HTML content. The i18n_interpolate_js function performs additional escaping, similar to the i18n_interpolate_html function, except that the string is escaped appropriately for use in JavaScript content.
  • Parameters
    • h: a pointer to a valid i18N_handle object.
    • str: a null-terminated string to subject to interpolation, as described above.
    • vars: a pointer to a valid i18n_vars object. This object is used to find values for all variables needed during string interpolation.
  • Returns: A null-terminated string containing the results of interpolation on the string str. Optionally, this string can also have been escaped for use in HTML or JavaScript content.

char *i18n_get(i18n_handle *i, char *tag, char *domain, i18n_vars *vars);
char *i18n_get_html(i18n_handle *i, char *tag, char *domain, i18n_vars *vars);
char *i18n_get_js(i18n_handle *i, char *tag, char *domain, i18n_vars *vars);

The _get functions are identical to the _interpolate functions, except that the message identified by domain and tag is fetched, and then interpolated.

char *i18n_strftime(i18n_handle *i, char *format, time_t time);
char *i18n_get_datetime(i18n_handle *i, time_t t);
char *i18n_get_date(i18n_handle *i, time_t t);
char *i18n_get_time(i18n_handle *i, time_t t);
  • Summary: these four functions get the time in the correct format for the current locale. Given a format that is identical to the one for strftime formats, the epochal time as found in time_t to the current locale settings
  • Parameters
    • i18n: the current i18n object.
    • format: the format to print the string in: %x, %X, and %C are useful.
    • t: The epochal time to format.
  • Returns: A pointer to a string formatted to the specified time

The i18n PHP Interface

  • Description: Constructor
  • Syntax: $i18n = new i18n (domain, languages)
  • Parameters
    • domain: sets the default domain to use for interpolation when domain is not explicitly specified.
    • langs: a comma-delimited list of supported locales specified in order of preference, for example, jp, sh, or en.
  • Returns: a new i18n object.

Object Methods

function i18N($domain = "", $langs = "")
  • Description: constructor
  • Parameters
    • domain: a string that describes the domain
    • langs: an optional string that contains a comma separated list of preferred locale. Most important locales appears first, that is, en_US, en_AU, zh, de_DE.

function get($tag, $domain = "", $vars = array())
  • Description: get a localized string
  • Parameters
    • tag: the tag of the string. Identical to the msgid string in the .po file
    • domain: the domain of the string in string. Identical to the .po or .mo file name without the extension. Optional. If not supplied, the one supplied to the i18n constructor is used
    • vars: a hash of variable key strings to value strings. Optional. If the hash contains “name” ⇒ “Kevin” and the string in question is My name is“, then “My name is Kevin” is returned.
  • Returns: a localized string if it is found or the tag otherwise.

function getJs($tag, $domain = "", $vars = array())
  • Description: get a localized string and encode it into JavaScript-friendly encoding
  • Parameters
    • domain: the domain of the string in string. Identical to the .po or .mo file name without the extension. Optional. If not supplied, the one supplied to the i18N constructor is used
    • vars: a hash of variable key strings to value strings. Optional. If the hash contains “name” ⇒ “Kevin” and the string in question is “My name is”, then “My name is Kevin” is returned.
  • Returns: a JavaScript-friendly localized string if it is found or the tag otherwise.

function getHtml($tag, $domain = "", $vars = array())
  • Description: get a localized string and encode it into HTML friendly encoding
  • Parameters
    • tag: the tag of the string. Identical to the msgid string in the .po file
    • domain: the domain of the string in string. Identical to the .po or .mo file name without the extension. Optional. If not supplied, the one supplied to the i18N constructor is used.
    • vars: a hash of variable key strings to value strings. Optional. If the hash contains “name” ⇒ “Kevin” and the string in question is “My name is”, then “My name is Kevin” is returned.
  • Returns: a HTML-friendly localized string if it is found or the tag, otherwise.

function interpolate($magicstr, $vars = array())
  • Description: get a localized string out of a fully qualified tag
  • Parameters
  • Returns: a localized string or magicstr if interpolation failed.

function interpolateJs($magicstr, $vars = array())
  • Description: get a localized string out of a fully qualified tag and encode it into JavaScript-friendly encoding.
  • Parameters
  • Returns: a JavaScript-friendly localized string or magicstr if interpolation failed.

function interpolateHtml($magicstr, $vars = array())
  • Description: get a localized string out of a fully qualified tag and encode it into HTML-friendly encoding
  • Parameters
  • Returns: a HTML-friendly localized string or magicstr if interpolation failed.

function getProperty($property, $domain = "", $lang = "")
  • Description: get a property value from the property file /usr/share/locale/<locale>/<domain>.prop. Properties are defined as <name>: <value>\n in the file. Each property is on its own line. Comments start with #.
  • Parameters
    • property: the name of the property in string
    • domain: the domain of the property in string. Optional. If not supplied, the one supplied to i18N constructor is used.
    • langs: an optional string that contains a comma separated list of preferred locale. Most important locales appears first, that is, en_US, en_AU, zh, de_DE. Optional. If not supplied, the one supplied to i18N constructor is used.

function getFile($file)
  • Description: get the path of the file of the most suitable locale, for example, if /logo.gif is supplied, locale ja is preferred, and/logo.gif, /logo.gif.en and /logo.gif.ja are available, /logo.gif.ja is returned.
  • Parameters
    • file: the full path of the file in question
  • Returns: the full path of the file of the most suitable locale.

function getAvailableLocales($domain = "")
  • Description: get a list of available locales for a domain or everything on the system
  • Parameters
    • domain: i18n domain in string. Optional
  • Returns: an array of locale strings.

function getLocales($domain = "")
  • Description: get a list of negotiated locales
  • Parameters
    • domain: i18n domain in string. Optional.
  • Returns: an array of locale strings, the first one being to most important, and so forth.

function strftime ($format = "", $time = 0)
  • Description: wrapper to strftime()
  • Parameters
    • format: the format parameter to strftime()
    • time: the epochal time
  • Returns: a strftime() formatted string

Internationalization Example

This is the code used to create this menu.

msgid "helloMenuItem"
msgstr "Bonjour"
msgid "helloMenuItem_help"
msgstr "Ceci dit Bonjour a la Monde"
msgid "helloMenu"
msgstr "Bonjour Monde App"
msgid "helloMenu_help"
msgstr "Ceci est l’application Bonjour Monde"
msgid "helloString"
msgstr "Bonjour Monde!"

This is the Makefile.

# Makefile for sample hello_world Sausalito application
VENDOR = sample
APP = hello
SRCS = en fr
I18NDIR = /usr/share/locale/
	# nothing to do for all
	for a in $(SRCS); do \
		mkdir -p $$DEST; \
		msgfmt -e$$a/$(APP).po -e -o $$a/$(VENDOR)-$(APP).mo; \
		install -o root -g root -m 644 $$a/*.mo $$DEST; \

Introducing the Cobalt Configuration Engine

The Cobalt Configuration Engine (CCE)

If the user interface is the face of the Sausalito Architecture, the Cobalt Configuration Engine (CCE) is the brains. CCE is the agent by which the user interface affects changes on a system.

It provides a unified interface to the task of configuring a system, and provides an abstraction layer between the user interface and the underlying system software.

CCE allows the development of a user interface that is truly flexible–it does not need to have intimate details about the underlying system. CCE is also designed to be extremely flexible, and allow developers to add new configuration options easily. Developers can extend CCE in the following ways:

  1. Add configuration definitions to define new configurable applications (classes).
  2. Add configuration information to extend the number of configurable options for an existing application (namespaces).
  3. Add to the list of things that CCE does when configurable options change (handlers).

Basic Concepts

CCE is broken into several logical units for easier understanding. The major pieces of the CCE system are:

  • The CCE daemon (CCED), which handles incoming connections, sessions, and signals.
  • The Cobalt Object Database (CODB), which maintains the object store that reflects the current configuration of the system.
  • The Cobalt System Configuration Protocol (CSCP), which is the protocol, or language, that CCE uses to communicate with clients.
  • The CCE client library (libcce), which provides routines for clients to better access CCE via CSCP.
  • The event handlers, which are the programs that make CCE changes take effect on the system itself.

CCED maintains the configuration state of the system in a set of objects representing the configurable applications, such as email and file sharing. These objects are stored internally by CODB. System configuration files are generated or modified by event handlers, which are triggered by a client making changes through CSCP. A client can be either a user interface, or a program written to interface with CCE.

FIXME Figure 5-1 CCE Block Diagram

How Data Flows Through CCE

From start to finish, getting data to do the right things and go to the right places can seem complicated. The general flow of data through CCE is as follows:

  • Packages register via configuration files for notification of when properties of objects change, or when objects are created or destroyed, which are commonly known as events.
  • CCED listens for incoming clients.
  • A client connects to CCED, which communicates using the CSCP protocol.
  • The client gets or sets properties, or creates or destroys objects to configure the system.
  • CCED determines which handlers need to run to actuate events from the client, and runs them.
  • The handlers communicate with CCED, if needed, via CSCP.
  • The handlers each do their work and exit, indicating their state of success. See “Method: bye( )” on FIXME page 5–34. If all handlers succeed, the changes are saved to the CODB. Otherwise, changes are ignored and discarded.
  • CCED returns the status of the transaction to the client via CSCP.

Figure 5–2 illustrates the flow of CCE data.

FIXME Figure 5-2 CCE Process Flow

The CCE Daemon

The CCE daemon (CCED) is the server process that implements the core of CCE. CCED accepts incoming client connections on a UNIX domain socket, and initiates the CSCP protocol; see “The Cobalt System Configuration Protocol (CSCP)” FIXME on page 5–5. Each incoming connection is handled by a child process of the master CCED process, leaving the master process to handle new connections and signals. While active, the child process is responsible for running handlers, maintaining and updating the object database, and for communicating with the client. The master process also catches signals delivered to it, such as an interrupt signal, and distributes the signal to all the children, accordingly.

To preserve data integrity, all CSCP write operations for all clients are serialized. This does not affect the performance of the system, because there are not typically multiple simultaneous administrative sessions. For several reasons, including security, file system access, and handler access, CCED must run as root. Users must authenticate to CCED to perform most tasks in order to protect the system: see “The AUTH Command” FIXME on page E–6.

This authentication is passed through the Linux system of Pluggable Authentication Modules (PAM). For more information on security in CCE, see “Introducing Cobalt Security” on FIXME page 7–1.

CCED Command-Line Parameters

Usually, CCED does not need command-line parameters. However, for debugging handlers or CCE itself, it is sometimes useful to change certain aspects of CCED’s behavior. The following command-line parameters are available:

Table 5–1 CCED Command-Line Parameters
-c directoryset the handler configuration directory, /usr/sausalito/conf is the default
-d numberset the debug mask; 0 = no debugging (default), 0xffffffff = full debugging and profiling
-nddo not run as a background daemon
-nfdo not fork child processes, handle only one client
-nhdo not run any handlers
-roread-only; do not save database changes; implies -nh
-st secondsset the client authkey timeout, 1 hour (3600 seconds) by default
-vprint version information and exit
-vvprint even more version information and exit

The Cobalt System Configuration Protocol (CSCP)

The Cobalt System Configuration Protocol (CSCP) is a simple protocol for communication between clients and the CCE, and between the CCE and event handlers. It is a text-based, newline delimited protocol, similar in form to FTP or HTTP. It is simple enough to be understood and debugged without the need for special tools.

To use CCE, you must use CSCP. The simplest way to use CSCP is with the command-line tool /usr/sausalito/bin/cceclient. This tool provides full access to CSCP directly, and is similar to using telnet to connect to TCP services. Wrapper libraries are provided for several popular languages to make CSCP easier to use from within programs.

For detailed information about the protocol specification, FIXME see Appendix E, “Cobalt System Configuration Protocol”.

The Cobalt Object Database (CODB)

The Cobalt Object Database (CODB), is similar in many respects to both traditional databases and object systems. It also differs in some significant ways. Every object stored within CODB has a unique identifier, its Object ID (OID), which CSCP uses to identify instances. Like traditional relational databases, CODB has a query language that allows the developer to access stored data. Unlike a traditional database, CCE uses CSCP, rather than SQL.

The traditional form of object manipulation is through object methods. These methods encapsulate and protect object data, stored in properties. CODB, by design, takes a different approach. The Sausalito system deals exclusively with properties. Unlike traditional object systems, there are no directly executing methods in Sausalito. Instead, Sausalito provides events and event handlers, which act as method code.


The structure of objects within CODB is defined by schemas which are provided by third- party vendors, Schemas, in the form of schema definition files, provide the class, property, and typedef definitions necessary to impose order on the data within CODB. The syntax of a schema definition file is simple XML, and is very flexible.

How to Read XML Syntax Descriptions

Before proceeding, it is prudent to briefly cover the pieces that make a file XML. XML is a plain-text file format, similar to HTML (or their common ancestor SGML). XML files are parsed, and the data in them is stored in a manner that is useful to the controlling application.


Throughout XML files, most whitespace characters (spaces, tabs, and newlines) are ignored. The only exceptions to this rule are within quoted strings and within the content field of an element. In these cases, called significant whitespace, whitespace is preserved.


To better represent the syntax used in this explanation, some symbols are necessary. Table 5–2 explains symbols herein.

Table 5–2 Symbols Used in Schemas
SPrepresents one whitespace character (space, tab or newline).
SQrepresents one single-quote (’).
DQrepresents one double-quote (”).
asterisk (*)represents zero or more occurrences of the previous expression.
plus (+)represents one or more occurrences of the previous expression.

Elements and Content

All XML files consist of one or more elements. Each element has a case-insensitive name and a set of zero or more attributes. Elements can, but are not required to have content. Each element is begun by a an opening tag with the following form:

"<" SP* name SP* attribute* SP* ">"

The content field follows the opening tag. Content fields are free form, and all characters are retained, including whitespace. The content of one element can be, and frequently is, one or more child elements. This containership is arbitrarily deep, and is defined by the specific XML format being used. The content field is terminated by a closing tag of the following form:

"</" SP* name SP* ">"

Because the content field is optional, it is frequently empty. A second form of opening tag is allowed, which indicates the absence of a content field:

"<" SP* name SP* attribute* SP* "/>"


As noted above, an element can have zero or more attributes. Attributes are always key-value pairs, and the value is always a quoted string. Attribute keys are always alphanumeric, and, like element names, are not case-sensitive. Attributes have the following form:

SP+ key SP* "=" SP* QU value QU


In addition to elements, XML files can include comments. Comments can be outside of any element, or in the content of any element. Comments begin with the string <!– and end with the string –>. Any text within a comment is ignored.

Escape Sequences

Because some characters, such as < and > are used by the XML language itself, it is necessary to use an alternate sequence of characters, called an escape sequence, to represent these reserved characters. The following escape sequences are recognized by XML:

Table 5–3 XML Escape Sequences
Literal CharacterEscape Sequence
< (less-than)&lt;
> (greater-than)&gt;
& (ampersand)&amp;
’ (apostrophe)&apos;
“ (quote)&quot;

Sample XML

<!-- This is a sample XML file, illustrating syntax -->
<XMLElement NAME="Sample">
	<SubElement name="Sub Sample 1">
		This is &lt;content&gt; for a &quot;SubElement&quot;
	<SubElement Name = "Sub Sample 2" Color="green"></SubElement>
		Name="Sub Sample 3" Note = "&amp;"/>

Schema Syntax

Schema definition files can include any of the following elements:


Syntax: SCHEMA

A SCHEMA is provided to identify a complete schema definition to the system. This element provides such information as schema name, vendor, version and any other information a vendor might find useful to store with their schema definition. All child elements of a schema are grouped together by the schema definition.

If no SCHEMA element is defined, or other top-level elements are defined, the non-schema-wrapped elements of the description file are assumed to be part of a schema with NAME set to the current filename (minus the .schema extension), and VENDOR and VERSION set to the empty string (”“). Sun CobaltTM recommends that every schema description file contain explicit SCHEMA elements, rather than rely on the default behavior

Element name: "SCHEMA"
Required attributes: "NAME", "VENDOR", "VERSION"
Optional attributes: any
Required content: none
Optional content: "CLASS" or "TYPEDEF" elements
Valid Parents: none
Table 5–4 SCHEMA Attributes
NAMEThe vendor-assigned name of the schema. This can be any string.
VENDORThe unique name of the schema’s vendor. This can be any string.
VERSIONThe vendor-assigned version of the schema. This can be any string, but by convention is an integer or floating point number for example: “1” or “3.1415”.

Syntax: CLASS

A CLASS is the formal definition of an object's structure. An object has all the properties of its CLASS, and only the properties of its CLASS.

Element name: "CLASS"
Required attributes: "NAME", "VERSION"
Optional attributes: "NAMESPACE"
Required content: none
Optional content: "PROPERTY" elements
Valid Parents: "SCHEMA"
Table 5–5 CLASS Attributes
NAMEThe unique name of the class being defined, or the name of the class being extended. This must be a C-style symbol, that is, it must start with a letter or underscore (_), followed by any number of letters, digits, or underscores. NAME should, per convention, start with an upper-case letter, for example: “Foo”.
VERSIONThe version number of this class structure. This can be any string, but by convention is an integer or floating point number for example: “1” or “3.1415”.
NAMESPACEThe optional name of the namespace being defined for the specified CLSASS. This follows the same rules as NAME, with the exception that NAMESPACE can be a blank string (”“), or be unspecified.


A PROPERTY is a sub-element of a CLASS. A single PROPERTY defines a single datum. CLASSES get their utility from their PROPERTY elements.

Element name: "PROPERTY"
Required attributes: "NAME", "TYPE"
Optional attributes: "DEFAULT", "OPTIONAL", "ARRAY", "READACL", "WRITEACL"
Required content: none
Optional content: none
Valid Parents: "CLASS"
Table 5–6 PROPERTY Attributes
NAMEThe name of the property. This must be a C-style symbol. See “Syntax: CLASS” on page 5–10 syntax for the NAME attribute. All properties beginning with an underscore (_) are reserved for future use. TYPE The data type of the property. This must be a valid TYPEDEF name. Type bindings are resolved after all schemas are loaded, so you can use a typedef before it is defined. A PROPERTY with a TYPE that does not exist will fail all data validation.
DEFAULTThe default value of the property, used when the property is unassigned. This can be any value that is valid for the specified TYPE. If DEFAULT is unspecified, the default value is an empty string (”“), which might be valid for the PROPERTY.
OPTIONALDefines whether the property can be the empty string (”“) in addition to a valid datum. This can be any string or unspecified. If unspecified or assigned the value ”“ or “0” (zero), the optional flag is set to false, otherwise, the optional flag is set to true.
ARRAYDefines whether the property is an array of the specified TYPE. This can be any string or unspecified. If unspecified or assigned the value ”“ or “0” (zero), the array flag is set to false, otherwise, the array flag is set to true. When set to true, data for this property is assumed to be an unbounded array of data, of the type specified.
READACLDefines the read access rule list for the property. This is a comma or space delimited list of security rules. If left blank or unspecified, the default value is ruleUser.
WRITEACLDefines the write access rule list for the property. This is a comma or space delimited list of security rules. If left blank or unspecified, the default value is ruleAdmin.


A TYPEDEF is a mechanism to build on the basic data typing provided by CCE. A TYPEDEF is a symbolic name given to a definition of a type, and is used by a PROPERTY to validate its data.

Element name: "TYPEDEF"
Required attributes: "NAME", "TYPE", "DATA"
Optional attributes: "ERRMSG"
Required content: none
Valid content: none
Valid Parents: "SCHEMA"
Table 5–7 TYPEDEF Attributes
NAMEThe symbolic name for the type. This must be a C-style symbol. See “Syntax: CLASS” on page 5–10 syntax for the NAME attribute.
TYPEThe validation class for the TYPEDEF. This must be either re or extern.
DATAThe TYPE appropriate data validator. For re TYPEs, it should be a valid regular expression. For extern TYPEs, it should be the path to an external program. The program should read the data from standard input, and return 0 if the data is valid, or non-zero if it is invalid.
ERRMSGThe error message returned by CCE when invalid data is written to an instance of this TYPEDEf. This can be any string, or unspecified.

Sample Schema Definition File

	NAME="Sample Schema"
	VENDOR="Sun Cobalt"
	<!-- Some classes, properties, namespaces, and types -->
	<CLASS name="SampleClass" version="12345">
		<PROPERTY name="name" type="sample_type" default="new"/>
	<CLASS name="SampleClass" namespace="Demo" version="6.02e23">
		<PROPERTY name="name" type="sample_type" default="123"/>
	<TYPEDEF name="sample_type" type="re" data="[A-Za-z0-9]*" />
	<CLASS name="SampleClass2" version="2.7183">
			readacl="ruleAdmin" writeacl="ruleAdmin"
		type="re" data="[A-Za-z0-9]*"
		errmsg="Yowie! You can&apos;t do that with a foo_type!"

Handler Registration

The format of a CCE handler configuration file (conf) is very simple with two or three whitespace-delimited fields per line, and one or more lines per file. Each line has the following format:

event <whitespace> handler <whitespace> stage

Any line that begins with a hash (#), or is blank is ignored.


The event field defines the circumstances upon which the handler is run. The event field follows the form:

This registers the specified handler to run whenever the specified class property is modified. To register a handler on an object’s creation or destruction, use the special properties _CREATE or _DESTROY. To register a handler on the modification of any property of a class, use the special property * (asterisk).:

Table 5–8 Valid Events
_CREATEWhen an object of the specified class is created.
_DESTROYWhen an object of the specified class is destroyed.
propertynameWhen the specified property of the specified class is modify.
*When any property of the specified class is modified.


The handler field defines the type of handler, and the type-specific handler details. It has the form:


The details of the handler depend on the type specified. The following types are available:

  • exec, which executes the file named in the details field.
  • perl, which sends the Perl script named in the details field through a persistent Perl process, for improved Perl performance.
  • test, which sends the contents of the details field to the standard output of CCED.

For exec and perl type handlers, which have a path name in the details field, some path expansion is performed. If the details field is a relative path (does not start with a /), the default handler path /usr/sausalito/handlers/ is prepended to the details field.


All handlers are run in one of several stages, and can thereby ensure some relative ordering. The available stages are VALIDATE, CONFIGURE, EXECUTE, TEST, and CLEANUP. The stage field is optional, and if left off, is assumed to be EXECUTE. Since handlers within a stage are not guaranteed to run in any specific order, a single application can register multiple handlers in each stage. Each stage’s name suggests what it can be used for. The VALIDATE stage, for example, should be used by handlers that do not make any changes, but instead verify that the requested event can be performed.

The final stage, CLEANUP, is meant for handlers which can not be undone. Handlers which register for this stage must not exit with a failure status, or the system can be left in an inconsistent and unrecoverable state.

File Naming

When searching for handler registration files, CCED will do a recursive search of the handler configuration directory. By default, this directory is /usr/sausalito/conf, but can be specified with the -c option to CCED, see “CCED Command-Line Parameters” on FIXME page 5–5. All files that end with .conf are parsed as handler registration files. The only exception to this is that any file or directory that begins with a dot (.) is ignored.

Sample Handler Registration File

# Register handlers for Class from AVendor
Class._CREATE	exec:/opt/AVendor/Class/Class_create		configure
Class._DESTROY	exec:/usr/sausalito/handlers/Class_destroy	test
Class.*		exec:AVendor/Class/Class_mod	perl:/usr/sausalito/bin/		validate

CCE Libraries

In order to make CSCP easier for programmers to use, code libraries are provided in several popular languages: C, Perl and PHP. These libraries insulate the users from the details of the CSCP protocol, and perform all the necessary conversions and transformations of data. The libraries are used both in the construction of the new user clients to the CCE server and to create handlers that extend the functionality of the CCE system.

All the libraries are similar in build and syntax, though there are minor variations among them to accommodate for language-specific feature sets. Each library builds functional wrappers around CSCP commands, as well as providing higher level functions for common tasks.

These libraries are under constant development, and will grow and evolve. As the libraries grow, some aspects of the library interfaces will inevitably become deprecated. All deprecated features will be retained for some time, for compatibility, but will eventually be removed from the libraries, so it is essential that new development not rely on deprecated features.


Dependencies and Headers


Struct: cce_error_t
Struct: cce_handle_t
Enum: cce_handler_ret
Struct: cce_props_t
Enum: cce_props_state_t
Typedef: cscp_oid_t


Function: cce_auth_cmnd( )
Function: cce_authkey_cmnd( )
Function: cce_authkey_cmnd( )
Function: cce_connect_cmnd( )
Function: cce_create_cmnd( )
Function: cce_destroy_cmnd( )
Function: cce_endkey_cmnd( )
Function: cce_find_cmnd( )
Function: cce_find_sorted_cmnd( )
Function: cce_get_cmnd( )
Function: cce_names_class_cmnd( )
Function: cce_names_oid_cmnd( )
Function: cce_set_cmnd( )
Function: cce_bad_data_cmnd( )
Function: cce_bye_handler_cmnd( )
Function: cce_connect_handler_cmnd( )
Function: cce_last_errors_cmnd( )
Function: cce_handle_new( )
Function: cce_handle_destroy( )
Function: cce_props_count( )
Function: cce_props_destroy( )
Function: cce_props_get( )
Function: cce_props_get_new( )
Function: cce_props_get_old( )
Function: cce_props_new( )
Function: cce_props_nextkey( )
Function: cce_props_reinit( )
Function: cce_props_set( )
Function: cce_props_set_old( )
Function: cce_props_state( )
Function: cce_array_deserial( )
Function: cce_list_destroy( )
Function: cscp_oid_from_string( )
Function: cscp_oid_to_string( )



Creating a New Object


Method: auth( )
Method: authkey( )
Method: bye( )
Method: classes( )
Method: connectuds( )
Method: create( )
Method: destroy( )
Method: endkey( )
Method: find( )
Method: findNSorted( )
Method: findSorted( )
Method: get( )
Method: names( )
Method: set( )
Method: whoami( )
Method: baddata( )
Method: connectfd( )
Method: info( )
Method: warn( )
Method: oid( )
Method: event_oid( )
Method: event_namespace( )
Method: event_property( )
Method: event_object( )
Method: event_old( )
Method: event_new( )
Method: event_is_create( )
Method: event_is destroy( )
Method: event_is modify( )

Making Sausalito-Aware Applications

This chapter provides information on creating applications that run on the Qube 3. To create an application, you must create a module that includes all the components needed and structure it so that it can be easily installed by users, in a package file format (.pkg). This chapter lists the fields that you need to include so that the Qube 3 can display the appropriate information during the installation process. It also describes the appropriate directories, files, and resources for your application module.

About the Application Module

The application module is a self-contained bundle of files, directories, and resources required for a new capability. Depending on the type of module you are creating, you choose the appropriate level of integration. Some modules trigger both the user interface and the back end system; others are stand alone modules.

New modules can contain any or all of the following code:

  1. User Interface (UI) modules
    • UI pages built using UIFC
    • Navigation nodes, such as adding buttons and menu items The Web mail service that is displayed on the Cobalt menu is an example of a service that is integrated only with the user interface and uses IMAP as its back-end system. The files for the user interface go into the ui directory; for more information about module directory layout, see FIXME Table 6—2 on page 6—5.
  2. Internationalization modules
    • Internationalization resources to translate the user interface into other languages.
  3. Back-end modules: Adding a user to the Qube 3 is an example of an instance that impacts only the back-end modules, where the existing user interface is used and the CCE configuration files and handlers are invoked.
    • CCE configuration files
    • CCE handlers
  4. Binary modules: These modules can be manually installed and completely unintegrated to the Cobalt User Interface (UI).
    • Service binary and configuration files, for example, email modules have SendMail and Majordomo binaries and modify the configuration files for these binaries.
    • Databases that register users as they are created and notify event handlers about creating users. This type of module uses the existing user interface.

Naming Your Application Module

Developers must use unique vendor-specific names for modules to avoid name conflicts.

NOTE: Cobalt uses base in its module names, for example, base-devel.mod. Developers must differentiate their modules by naming the modules with a distinctive name, preferably a name that reflects their company or product, for example, vendor_name_module.

Building a New Service Module

A service module is a self-contained bundle of files or directories and resources required for a new capability, for example, an ecommerce product or a system backup product.

New modules can contain any or all of the following:

  • Navigation nodes service.xml
  • User Interface (UI) pages built using UIFC service.php
  • Internationalization resources service.po
  • CCE configuration files service.schema, service.conf
  • CCE handlers, serviceMod.c
  • Service binaries and configuration serviced

NOTE: You can write handlers in any language. Cobalt provides bindings for C and Perl.

Cobalt enabling tools include:

  • Standard directory structure document; see Figure 6—7 on page 6—22.
  • Build tools to create loadable module files (scripts and a Makefile)

Making your Application into a Package

This section describes the skeleton module for Sausalito. By customizing the skeleton module for your needs, you can integrate seamlessly into the Cobalt configuration environment.

To build a service module:

  1. Create handlers to interact with the Cobalt Configuration Engine (CCE). A configuration file goes in glue/conf; the actual handlers go in glue/handlers.
  2. Create any user interface components, if necessary. These include web and menu page descriptors, which go in the ui/web and ui/menu directories, respectively.
  3. Write any locale files; these go in the locale directory.
  4. Look at templates/spec.tmpl and templates/packing_list.tmpl.
  5. Look at the top-level Makefile. Adjust the variables to fit your situation.

The default build targets are make all, make clean, make install, and make rpm.

NOTE: The default template to build RPM files is in /usr/sausalito/devel/templates. If you want to modify these templates, create a template directory in your module. Copy these files to your template directory and modify them as needed.

A sample skeleton module is available in the Cobalt Developer web page. Go to for the code sample and Readme file.

Here’s some more information about the default make rules and expected file names:

Table 6—1 The top-level Makefile variables
MakefileVariables Description
VENDORthe vendor field for your module
VENDORNAMEthe actual vendor name; this name can be the same as VENDOR
SERVICEthe name for the service
VERSIONversion number
RELEASErelease number
BUILDARCHset to noarch if you don’t want platform-specific RPMs generated.
XLOCALEPATset to a space-separated list of locale patterns to exclude
BUILDUIpackages all files in ui/web and ui/menu.
BUILDLOCALEset to yes to build these components, create RPMs, and create a capstone RPM.
BUILDSRCbuild the files is in the src directory.
BUILDGLUEIf BUILDGLUE is set to yes, packages all the handlers, object schemas, configuration files for event triggers, and conf files. If set to no,
BUILDGLUEdoes no packaging.
DEFLOCALEThis locale is used for static HTML pages, for example, en or ja.

The BUILD variables determine which directories to include when calling the clean, install, and rpm targets.

The default make rules take the BUILD? variables and build up ui, glue, and locale RPMS, if requested. If any of these RPMS are generated, a capstone RPM is created as well. A capstone is a type of packing list for the RPMs.

Table 6—2 Module Directory Layout
constructorcapstone constructors
destructorcapstone destructors
gluehandler and configuration modification code
uiuser interface and user interface menu code
localelocale information and locale-specific UI pages
templatesuser-modifiable template files used in packing list and RPM generation
srcsrc directory (optional)
RPMSRPMS directory (optional)
SRPMsource RPMS directory (optional)

The default make rules expect the following file layout:

  1. glue/conf/*
  2. locale/localeX/$(SERVICE).po
  3. ui/menu/*
  4. constructor/*

The default make rules place these files in the following locations:

glue/conf/* -> $(CCEDIR)/conf/$(VENDOR)/$(SERVICE)/*
	glue/handlers/* -> $(CCEDIR)/handlers/$(VENDOR)/$(SERVICE)/*
locale/localeX/$(SERVICE).po -> /usr/share/locale/localeX/LC_MESSAGES/$(VENDOR)-$(SERVICE).mo
ui/menu/* -> $(CCEDIR)/ui/menu/$(VENDOR)/$(SERVICE)/*
	ui/web/* -> $(CCEDIR)/ui/web/$(VENDOR)/$(SERVICE)/*
constructors/* -> $(CCEDIR)/constructor/$(VENDOR)/$(SERVICE)/
	*destructors/* -> $(CCEDIR)/destructor/$(VENDOR)/$(SERVICE)/*

If your module does not contain compiled code, the above make rules should be all that you need for building a service module. Otherwise, you need to know about a couple additional make rules. First, make checks for Makefiles in the glue, src, and ui directories and uses them, if they are present. You must prepend the PREFIX environment variable on the install phase of the Makefile so that RPMs are properly generated.

In addition, the make rpm rule does not touch the src directory, so you must create any RPMs you want from separate specification files. templates/packing_list.tmpl should be updated to reflect any of these RPMs without version numbers. You should create a file with the same name as the RPM in the rpms directory to get the appropriate version included in the packing list.

Finally, you might need to edit templates/rpmdefs.tmpl to add additional build, install, and file targets for any files that you have. The <begin [$%]VARIABLE> sections in the rpmdefs.tmpl file correspond to the same [VARIABLE_SECTION] sections in templates/spec.tmpl. If you want to add something to spec.tmpl that is not dependent upon a single RPM, you can directly add it to spec.tmpl.

NOTE: If you have a VENDORNAME specified, make searches first in {glue, locale, ui, src}/$(VENDORNAME) for files before searching in the glue, locale, ui, and src directories.

Introducing Slush Barn, A Real-World Application

Here is an example of how to create a new Sausalito module. The goal of this example is to manage of barn of animals using a UIFC-enabled front-end while updating an XML file on the server. This example is included to help you better understand how the pieces of the Sausalito architecture work together to form a simplified means of creating web-based server administration tools.

The files created in making this module are listed in below. Although many files are needed for this module to work properly, each file is usually very short and serves its purpose. Details on the syntax and contents of each file type are listed throughout this manual.

NOTE: These code modules are given the vendor-specific name slush so that they are differentiated from Sausalito standard files. For a list of standard files, see Appendix D, Base Data Types.

  • slush-barn.mod/Makefile
  • slush-barn.mod/glue/conf/barn.conf
  • slush-barn.mod/glue/handlers/
  • slush-barn.mod/glue/schemas/animal.schema
  • slush-barn.mod/glue/handlers/
  • slush-barn.mod/ui/menu/barn.xml
  • slush-barn.mod/ui/web/animal.php
  • slush-barn.mod/ui/web/animalHandler.php
  • slush-barn.mod/ui/web/slaughter.php
  • slush-barn.mod/locale/en/animal.po

The data types are registered with CCE using a typedef and a class tag within the XML file animal.schema. The typedef called animalType defines a new type that might contain only the strings Pig, Cow, Horse, and Chicken. The class itself is called BarnAnimal and has two properties. The name property refers to the given name of that particular barn animal, and the type property is defined as being of type animalType. Each time an addition is made to our barn, a new instance of the class BarnAnimal is created and it s properties are filled with the data entered by the user.

Event handlers are also registered with CCE These event handlers are found within the barn.conf file. As defined, our handler ( is called upon any creation, change or destruction of a BarnAnimal instance. The handler in turn uses the data entered to create and update an XML file called /etc/barn.conf, but any types of service configuration can occur here. as the handler is run as root if triggered by the admin user.

The logic to the user interface is very simple. A listing of all the currently known animals is listed in the barn.php file using a ScrollList type. This type allows for multiple columns of data along with formatting rules making for a clear and distinct separation between the logic and presentation of the user interface. The ModifyButtons and the AddButton on this page link to a page called animal.php, which is generic in that it allows for both the creation and manipulation of animals within the barn. These actions are done in the page named animalHandler.php, which receives the POST of the animal.php page. To remove an animal from the barn, the slaughter.php page is called along with the OID of the object to be deleted.

In order for our pages to be linked within our site, we need to create the XML tree node. This file is called barn.xml and contains information regarding that node. An ID is assigned to every node of the tree as a reference point when creating parent-child relationships. In this example, you can manipulate objects in a barn.

NOTE: No animals were harmed in the making of this application.

The new page is shown in Figure 6—1.

FIXME Figure 6—1 Manipulating Barn Objects

How to Install your Package File on the Qube 3

There are two ways that packages can be installed on Qube:

  • manually
  • update server

Both these ways provide information about the package, that is, package meta-information, before the user installs the package. This meta-information includes fields with the package name, vendor, description, license, and whether package dependencies exists; these fields are described in Table 6—3 on page 6—12. This information is needed to properly display in the Qube UI details about the package before its installed. To provide this information, this information is included in the package list and the package information directories for each package.

Update servers alert you if they have new software for your Qube 3. When the Qube is alerted that there is a new version of software for the Qube, the update server and Qube have the following dialog:

  1. The Qube 3 queries the server for information about new software. It provides details about the Qube including the packages installs, Qube identification, and so forth.
  2. The update server replies with list of available packages with associated information, such as license and locale information. This informations corresponds to the packing_list and the contents of the pkginfo directory.
  3. If an InfoURL field is specified, a popup window with the URL is displayed when you go to the install detail page. If an InfoURL field is not specified, a short description of the package is displayed.
  4. Installation can be selected.

The events around the manual installation are as follows:

  1. The user on the Qube enters the package location through either browser upload, URL download, or putting the file in /home/packages.
  2. The Qube prepares the package for installation and displays the installation page. This informations corresponds to the packing_list and the contents of the pkginfo directory.
  3. The contents of the installation page display a short description of the package that is to be installed.
  4. Installation can be selected.

Installation Process

The following stages occur in the installation process:

  • If the package requires the server to reboot, the user is prompted to reboot the machine.
  • The install process looks first for a splash page If the splash page specifies the pre-installation option, it will look for an index.cgi or index.php page to call. It will pass in the following two variables a GET request to these files: submiturl and cancelurl.

NOTE: The splash page optionally specifies a pre-installation page, which allows developer to create a custom page for the package including license information. This page must be a CGI or PHP page that accepts GET requests.

  • If the splash page doesn t exist and the license field does, BlueLinQ will present a standard license page containing the value of the license field.

NOTE: The Qube 3 software notification mechanism is called BlueLinQ.

Once the user accepts the license (if there is a license), BlueLinQ checks package dependencies, and halts if there is a dependency error. If not, BlueLinQ runs the preinstallation scripts, install RPMS, and then runs the post-installation script. The scripts are located in the scripts directory of the package.

NOTE: BlueLinQ will install an RPM only if it is newer than any existing RPMs. If there is an existing RPM on the server, BlueLinQ increments the reference count each time you add a package with a RPM referenced in it. When you uninstall a package, the reference count is reduced. If the reference count for a package is less than one, BlueLinQ deletes the RPM.

Choices for the Installation Process

You can customize your installation. You can change the look and feel of install by opting to include:

  • an infoURL field
  • a splash page
  • a generic license

The splash page must be a CGI or PHP file. The update process calls this CGI with the following URL variables set: submitURL and cancelURL.

Package Structure

The package file format is a tar.gz file. When you install a package file, BlueLinQ checks for the following items:

  • whether the file is a tar file or a compressed tar file
  • whether the file is signed

In packages for earlier Cobalt products, package files had the following elements:

  • packing_list
  • RPMs
  • SRPMs
  • install_me script

Packages for earlier Cobalt products had scripts that performed all installation tasks. Package dependency checking was done by the package itself. New packages have scripts that runs at specified times.The scripts deal with the following issues:

  • pre-installation
  • post-installation
  • pre-uninstallation
  • post-uninstallation

BlueLinQ runs these scripts as part of the installation. Package dependencies are based on vendor name, version number and package name. You can evaluate version number to determine if they are equal, less than, or greater than the target version. Sausalito currently checks a three-part field, for example, 1.0 or 1.1.2.

The new packing list format includes the following elements as shown in Table 6—3.

NOTE: All the information in the package list format is case-sensitive.

Table 6—3 Package List Format
[Package – Version=1.0]
Vendorvendor name can include alphabetical characters, numbers, underscore (_), and the plus sign (+). Spaces and hyphens (-) are not permitted.
VendorTaginternationalizable vendor string
Namepackagename can include alphabetical characters, numbers, underscore (_), and the plus sign (+). Spaces and hyphens (-) are not permitted.
NameTag:internationalizable package name string.
Categorycategory information can include alphabetical characters, numbers, underscore (_), and the plus sign (+). Spaces and hyphens (-) are not permitted.
LocationURL that specifies the package download location
InfoURLadditional information URL. Optional. Use this if you want to display a new site (as opposed to installing a package).
InfoURLoptions options that should be sent with to the URL, which can include serial number, product identifier (product), and vendor name (name).
Versionversion of the package
Version TagInternationalizable version number.
Sizesize in bytes (only used by the update server.)
Product: NOTE: use this field to specify as many products as you are including. Include one line for each package. You can use a regular expression to specify products, for example: (4000|4010|4100) WG.Cobalt product requirements: for example, 4100WG or 4nnnWG. NOTE: 4000WG is the product number for the basic Qube 3. 4010WG is the product number for the Qube 3 with caching; 4100WG is the product number for the Qube 3 with caching and mirroring.
PackageTypespecify complete or update
Optionsuninstallable, reboot, refreshui, refreshcce
LongDescinternationalizable long description
ShortDescinternationalizable short description
Copyright:internationalizable copyright string
Licenseinternationalizable license information. Optional
Splashpre-install, post-install, pre-uninstall, post-uninstall
Depend NOTE: Each dependency must be on its own line. See Package Dependency Model on page 6—16 for more information.package dependencies. for example, vendor:package. The package won’t show up in the new or updates pages if these dependencies aren’t met. Here’s what’s expected: vendor:package vendor-package must exist. vendor:package ! vendor-package must not exist. vendor:package <=> version vendor-package is less than, equal to, or greater than the specified version number. vendor:package != version vendor-package not equal to version.
VisibleDepend NOTE: Each dependency must be on its own line. See Package Dependency Model on page 6—16 for more information.just like Depend except that the package will show up in the new or updates lists even if dependencies aren’t met.
Obsoletes NOTE: Each obsoletes must be on its own line. See Package Dependency Model on page 6—16 for more information.obsoletes vendor-packages format: vendor:package vendor:package ⇔ version
RPMused only by the actual package
SRPMused only by the actual package

NOTE: Internationalized strings are in the following format: [[vendor]]. If you are specifying strings within the pkginfo locale directory, then do not specify a domain. Sausalito specifies the domain for you. pkginfo locale strings cannot include locale tags within locale tags. You can include locale tags that refer to other domains.

Package files have the following structures. Figure 6—2 shows the package file structure.

FIXME Figure 6—2 Package File Structure

See Module File Hierarchy on page 6—22 for a more complete file hierarchy.

NOTE: The packing_list format for packages is very similar to the package part of the package_list update server packing list. You can use them interchangeably with the caveat that some fields are unused. For example, the update server information uses the size field. The packing list uses RPM, SRPM, and fileName.

The following features are only used by software update notification mechanism (BlueLinQ):

  • Size (in bytes)
  • InfoURL
  • Location
  • PackageType

The following fields are only used by actual package installation mechanism:

  • RPM
  • SRPM
  • Options

Package Dependency Model

The dependency model allows you to restrict packages to particular Cobalt products, for example, the Qube 3. You can also include dependencies on other software packages. Finally, you can declare old packages obsolete.

The format for dependency requires that each dependency is on a separate line with a label denoting the type of dependency. Sausalito offers three types of dependency information:

  • Product: Cobalt Product Dependency such that the package will install if other software products that are needed are not already installed. These are checked by product ID, for example 4000WG. You can use a specific product, particular version, or you can use a Perl regular expression here.
  • Package dependencies:
    • Depend: Normal package dependency based on the version number being less than (<), equal to (=), or greater than (>) the version number specified.
    • VisibleDepend: Visible dependency: same as Depend but is only useful for the software update mechanism. The packages that do not meet dependencies behave identically to the Depend in all other manners to new or update packages despite the fact that the package can t be installed.
  • Obsoletes: Obsoletes packages name or name and optional version, less than (<), equal to (=), or greater than (>) the version number specified, which removes information about other packages of that name or version number specified.

Information for Installing Stand-alone Packages

The following are used in the actual package installation process but not in update server-supplied information. They are not used for the update server pkginfo.

  • RPM
  • SRPM
  • Options (in a comma-separated list) include:
    • reboot
    • refreshui
    • refreshcce
    • uninstallable

These fields are used to provide information and are included in the actual package as well as provided by the update servers:

  • Package identification
    • Name and nametag
    • Version and versionTag
    • Vendor and vendorTag
  • Description
    • shortDesc
    • longDesc
  • License information
    • License
    • Splash
  • Category

These fields are found only in update server package:

  • Size (in bytes)
  • PackageType: complete or update
  • Location
  • InfoURL: a pop-up window appears when the user clicks the magnifying glass

FIXME Figure 6—3 New Software Installed

FIXME If you click on the magnifying glass, you see the information shown in Figure 6—4, which corresponds to the information in Table 6—3 on page 6—12.

FIXME Figure 6—4 New Software Installation Details

Software Update Server

NOTE: If the infoURL file exists, it displays a popup window and will not install the actual package.

The BlueLinQ tab on the Qube 3 has an Updates menu. This page lists available software with the following information.

  • Update server-provided information (name, vendor, locale, description)
  • Pop-up information. InfoURL displays the URL to be passed the Qube s serial number
  • The package checks for an InfoURL. If one exists, the page referenced by the InfoURL appears. If not, the package presents the license information, and installs after the user accepts the license agreement.

When users click on Install Details, the Qube 3:

  • Displays the splash page if there is one or displays a license agreement in standardized license format.
  • Begins installation

When the user begins installation, these events occur on the Qube 3:

  • It checks for a signature and attempts to authenticate it, if one is present. If the signature cannot be authenticated, a message is displayed letting the user know that the signature check failed.
  • It runs the preinstallation script.
  • It installs the Redhat Package Modules (RPMs).
  • It runs the postinstallation scripts.
  • It reboots or refreshes, if those options are set.

NOTE: Cobalt Networks uses Redhat Package Manager (RPM) files because applications are easy to manage if they are installed using RPM utilities. For details on creating *.rpm files (also known as redhat package module files), see Maximum RPM, by Marc Ewing and Erik Troan. Maximum RPM is the definitive technical reference for the RPM packaging system; it provides information on RPM’s history, usage, and internals from both the user and packager perspectives. Also, see for the most up-todate information about RPM technology.

Figure 6—5 shows the Update Server page.

FIXME Figure 6—5 Update Software Installed

FIXME If you click on the magnifying glass, you see the information shown in Figure 6—6, shown in Figure 6—4, which corresponds to the information in Table 6—3 on page 6—12.

FIXME Figure 6—6 Update Software Installation Details

Development Details

Modules expect the following auxiliary support from Sausalito development tools:

  • SAUSALITO/devel/ for all the Makefile rules.
  • SAUSALITO/bin/mod_rpmize for the RPM specification file generator.

FIXME Figure 6—7 Module File Hierarchy

User Interface Foundation Classes

This appendix is a complete reference for all User Interface Foundation Classes (UIFC). The UIFC is a comprehensive set of class libraries for Cobalt's user interface components. Their functions include generation of HTML code for rendering and JavaScript code for error checking. “Utility Classes” on page B–1 describes classes that work in conjunction with the UIFC classes.

To use UIFC, you should have some basic knowledge about object-oriented design and programming as well as PHP, because UIFC is object-oriented and implemented in PHP.

The UIFC were designed to provide both user interface consistency and flexibility. HtmlComponentFactory is the first class you should look at. It is a factory that constructs UIFC class in the most commonly used way. See “HTMLComponent” on page A–22. Each UIFC class is listed in this appendix in alphabetical order.

HTML Generation

UIFC contains classes of visual components. The classes have methods to generate the look and feel in HTML. For example, the IpAddress class generates HTML code that represents an IP address data type. In this way, a change in look and feel of a visual component within the whole user interface can be accomplished by modifying just one class.

Error Checking

Form fields in UIFC support the plug-in of JavaScript error checking code. This feature is useful for checking and reporting errors interactively. Not all form fields require error checking because their input set might be limited to valid data. For more information of error handling, see “Error” on page B–3.

Reusable Code

The class hierarchy of UIFC is designed to be reusable. It is easy to subclass a UIFC class and make a more specific visual component, for example: a class B IP address, can be made by subclassing the IpAddress class. FormFieldBuilder also generates HTML code.

Common Pitfalls

There are several things to avoid when using UIFC:

  • The UIFC encompass many functions. You must pay special attention in extending UIFC classes to add new functionality. New functionality can introduce inconsistencies if the functionality does not occur in the existing user interface.
  • Because UIFC is written in PHP and PHP does not have good support for objectoriented programing, UIFC users can directly refer to private variables and methods of UIFC classes. For good programming practice, do not do this because these functions could change in the future.
  • Do not use UIFC to format free-flow text paragraphs. Pure HTML provides more formatting capabilities than UIFC. You can put HTML inside UIFC pages.
  • The toHeaderHtml() method of Page object outputs HTTP headers. Do not print anything before this method. As a common PHP catch, blank lines are printed. The following code provides a warning because there is a blank line above the method:
/* Other code... */
  • Because PHP is interpreted and is basically typeless, it is very easy to pass in parameters of wrong types to functions or methods. This can generate runtime errors from UIFC classes that your code does not use directly.

Utility Classes

FIXME: Need to add

About Style

FIXME: Need to add

Base Data Types

FIXME: Need to add

Cobalt System Configuration Protocol

FIXME: Need to add

CCE Class Definitions

FIXME: Need to add

info/devel/devguide.txt · Last modified: 2018/07/18 17:34 by