GNU Pies Manual (split by chapter):   Section:   Chapter:FastBack: Dependencies   Up: Top   FastForward: Pies Debugging   Contents: Table of ContentsIndex: Concept Index

3 Pies Configuration File

Pies reads its settings and component definitions from one or more configuration files. The default configuration file is named pies.conf and is located in the system configuration directory (in most cases /etc or /usr/local/etc, depending on how the package was compiled). This file uses the native Pies configuration syntax. Apart from this format, the program also understands configuration files in inetd and meta1 formats.

Alternative configuration files may be specified using --config-file (-c command line option), e.g.:

pies --config-file filename

Any number of such options may be given. The files named in --config-file options are processed in order of their appearance in the command line. By default, pies expects configuration files in its native format. This, however, can be changed by using the --syntax=format command line option. This option instructs pies that any configuration files given after it have are written in the specified format. Valid formats are:


Pies native configuration file format.


Inetd-style configuration format.


MeTA1-style format.


Format of the /etc/inittab file (see Init Process).

The configuration file format set by the --syntax option remains in effect for all --config-file options that follow it, up to the end of the command line or the next occurrence of the --syntax option. This means that you can instruct pies to read several configuration files of various formats in a single command line, e.g.:

pies --config-file /etc/pies.conf \
     --syntax=inetd --config-file /etc/inetd.conf \
     --syntax=meta1 --config-file /etc/meta1/meta1.conf

The rest of this chapter concerns the pies native configuration file format. You can receive a concise summary of all configuration directives any time by running pies --config-help. The use of inetd configuration files is covered in inetd and the use of meta1 configuration files is described in include-meta1

If any errors are encountered in the configuration file, the program reports them on the standard error and exits with status 78.

To test the configuration file without actually starting the server, the --lint (-t) command line option is provided. It causes pies to check its configuration file and exit with status 0 if no errors were detected, and with status 78 otherwise.

Before parsing, configuration file is preprocessed using m4 (see Preprocessor). To see the preprocessed configuration without actually parsing it, use -E command line option.

3.1 Configuration File Syntax

The configuration file consists of statements and comments.

There are three classes of lexical tokens: keywords, values, and separators. Blanks, tabs, newlines and comments, collectively called white space are ignored except as they serve to separate tokens. Some white space is required to separate otherwise adjacent keywords and values.


Comments may appear anywhere where white space may appear in the configuration file. There are two kinds of comments: single-line and multi-line comments. Single-line comments start with ‘#’ or ‘//’ and continue to the end of the line:

# This is a comment
// This too is a comment

The following constructs, appearing at the start of a line are treated specially: ‘#include’, ‘#include_once’, ‘#line’, ‘# num’ (where num is a decimal number). These are described in detail in Preprocessor.

Multi-line or C-style comments start with the two characters ‘/*’ (slash, star) and continue until the first occurrence of ‘*/’ (star, slash).

Multi-line comments cannot be nested.

3.1.2 Statements

A simple statement consists of a keyword and value separated by any amount of whitespace. The statement is terminated with a semicolon (‘;’).

Examples of simple statements are:

pidfile /var/run/;
source-info yes;
debug 10;

A keyword begins with a letter and may contain letters, decimal digits, underscores (‘_’) and dashes (‘-’). Examples of keywords are: ‘group’, ‘control-file’.

A value can be one of the following:


A number is a sequence of decimal digits.


A boolean value is one of the following: ‘yes’, ‘true’, ‘t’ or ‘1’, meaning true, and ‘no’, ‘false’, ‘nil’, ‘0’ meaning false.

unquoted string

An unquoted string may contain letters, digits, and any of the following characters: ‘_’, ‘-’, ‘.’, ‘/’, ‘:’.

quoted string

A quoted string is any sequence of characters enclosed in double-quotes (‘"’). A backslash appearing within a quoted string introduces an escape sequence, which is replaced with a single character according to the following rules:

SequenceReplaced with
\aAudible bell character (ASCII 7)
\bBackspace character (ASCII 8)
\fForm-feed character (ASCII 12)
\nNewline character (ASCII 10)
\rCarriage return character (ASCII 13)
\tHorizontal tabulation character (ASCII 9)
\vVertical tabulation character (ASCII 11)
\\A single backslash (‘\’)
\"A double-quote.

Table 3.1: Backslash escapes

In addition, any occurrence of ‘\’ immediately followed by a newline character (ASCII 10) is removed from the string. This allows to split long strings over several physical lines, e.g.:

"a long string may be\
 split over several lines"

If the character following a backslash is not one of those specified above, the backslash is ignored and a warning is issued.


Here-document is a special construct that allows to introduce strings of text containing embedded newlines.

The <<word construct instructs the parser to read all the following lines up to the line containing only word, with possible trailing blanks. Any lines thus read are concatenated together into a single string. For example:

A multiline

Body of a here-document is interpreted the same way as double-quoted string, unless word is preceded by a backslash (e.g. ‘<<\EOT’) or enclosed in double-quotes, in which case the text is read as is, without interpretation of escape sequences.

If word is prefixed with - (a dash), then all leading tab characters are stripped from input lines and the line containing word. Furthermore, if - is followed by a single space, all leading whitespace is stripped from them. This allows to indent here-documents in a natural fashion. For example:

<<- TEXT
    All leading whitespace will be
    ignored when reading these lines.

It is important that the terminating delimiter be the only token on its line. The only exception to this rule is allowed if a here-document appears as the last element of a statement. In this case a semicolon can be placed on the same line with its terminating delimiter, as in:

help-text <<-EOT
        A sample help text.

A list is a comma-separated list of values. Lists are delimited by parentheses. The following example shows a statement whose value is a list of strings:

dependents (pmult, auth);

In any case where a list is appropriate, a single value is allowed without being a member of a list: it is equivalent to a list with a single member. This means that, e.g. ‘dependents auth;’ is equivalent to ‘dependents (auth);’.

A block statement introduces a logical group of another statements. It consists of a keyword, followed by an optional value, and a sequence of statements enclosed in curly braces, as shown in the example below:

component multiplexor {
        command "pmult";

The closing curly brace may be followed by a semicolon, although this is not required.

3.1.3 Using Preprocessor to Improve the Configuration.

Before parsing, configuration file is preprocessed. This goes in three stages. First, include directives are expanded. An include directive begins with a ‘#’ sign at the beginning of a line, followed by the word ‘include’ or ‘include_once’. Any amount of whitespace is allowed between the ‘#’ and the word. The entire text up to the end of the line is removed and replaced using the following rules:

#include <file>
#include file

The contents of the file file is included. There are three possible use cases.

If file is an absolute file name, the named file is included. An error message will be issued if it does not exist.

If file contains wildcard characters (‘*’, ‘[’, ‘]’ or ‘?’), it is interpreted as shell globbing pattern and all files matching that pattern are included, in lexicographical order. If no matching files are found, the directive is replaced with an empty line.

Otherwise, the form with angle brackets searches for file in the include search path, while the second one looks for it in the current working directory first, and, if not found there, in the include search path. If the file is not found, an error message will be issued.

The include search path is:

  1. Any directories supplied with the -I (--include-directory) command line option. These directories are scanned in the same order as they appear in the command line.
  2. prefix/share/pies/1.4/include
  3. prefix/share/pies/include

where prefix is the installation prefix.

#include_once <file>
#include_once file

Same as #include, except that, if the file has already been included, it will not be included again.

The obtained material is then passed to m4 for preprocessing. For a complete user manual, refer to In this subsection we assume the reader is sufficiently acquainted with m4 macro processor.

The external preprocessor is invoked with -s flag, instructing it to include line synchronization information in its output. This information is then used by the parser to display meaningful diagnostic. An initial set of macro definitions is supplied by the pp-setup file, located in $prefix/share/pies/1.4/include directory.

The default pp-setup file renames all m4 built-in macro names so they all start with the prefix ‘m4_’. This is similar to GNU m4 --prefix-builtin options, but has an advantage that it works with non-GNU m4 implementations as well.

The include path for m4 is set as described above.

Additional preprocessor symbols may be defined and existing definitions cancelled using the following command line options:

-D symbol[=value]

Define symbol sym as having value, or empty, if the value is not given.

-U sym

Undefine symbol sym.

Finally, the m4 output is passed to the configuration parser. When parsing, the following constructs appearing at the beginning of a line are handled specially:

#line num
#line num "file"

This line causes the parser to believe, for purposes of error diagnostics, that the line number of the next source line is given by num and the current input file is named by file. If the latter is absent, the remembered file name does not change.

# num "file"

This is a special form of #line statement, understood for compatibility with the C preprocessor.

3.2 The component Statement

Config: component

The component statement defines a new component:

component tag {

The component is identified by its tag, which is given as argument to the component keyword. Component declarations with the same tags are merged into a single declaration.

The following are the basic statements which are allowed within the component block:

Config: component: mode mode

Declare the type (style) of the component. Following are the basic values for mode:


Define a ‘respawn’ component (see respawn). This is the default.


Define an ‘inetd-style’ component (see inetd-style).


Define a ‘meta1-style’ component (see meta1-style).


Define a ‘accept-style’ component (see accept-style).


The component is run right after startup. Prior to starting any other components, pies will wait for all startup components to terminate.


These components are started as a part of program shutdown sequence, after all regular components have terminated.

When run as init process (see Init Process), the following modes are also allowed:


The process will be executed during system boot. The ‘runlevel’ settings are ignored.


The process will be executed during system boot. No other components will be started until it has terminated. The ‘runlevel’ settings are ignored.


The process will be executed when pies receives the SIGINT signal. Normally this means that the CTRL-ALT-DEL combination has been pressed on the keyboard.


The process will be executed when a signal from the keyboard handler is received that indicates that a special key combination was pressed on the console keyboard.


The process will be executed once when the specified runlevel is entered.


The process will be executed when the specified ondemand runlevel is called (‘a’, ‘b’ and ‘c’). No real runlevel change will occur (see Ondemand runlevels). The process will remain running across any eventual runlevel changes and will be restarted whenever it terminates, similarly to respawn components.


The process will be executed when the power goes down. Pies will not wait for the process to finish.


The process will be executed when the power is failing and the battery of the external UPS is almost empty.


The process will be executed as soon as pies is informed that the power has been restored.


The process will be executed when the power goes down. Pies will wait for the process to finish before continuing.


The process will be executed during system boot, before any boot or bootwait entries. The ‘runlevel’ settings are ignored.


The process will be started once when the specified runlevel is entered. Pies will wait for its termination before starting any other processes.

Config: component: program name

Full file name of the component binary. This binary will be executed (via /bin/sh -c) each time pies decides it needs to start the component.

To supply command line arguments, use command statement.

Config: component: command string

Command line for the program. The argument should be just as arguments normally are, starting with the name of the program. The latter may be different from the one specified to program statement. Its value will be available to the program as argv[0].

Config: component: flags (flag-list)

Define flags for this component. The flag-list is a comma-separated list of flags. Valid flags are:


This component is disabled, i.e. pies will parse and remember its settings, but will not start it.


Do not close standard input. Redirect it from /dev/null instead. Use this option with commands that require their standard input to be open (e.g. pppd nodetach).


Mark this component as precious. Precious components are never disabled by pies, even if they respawn too fast.


Run command as /bin/sh -c "$command". Use this flag if command contains shell-specific features, such as I/O redirections, pipes, variables or the like. You can change the shell program using the program statement. For example, to use Korn shell:

component X {
  flags shell;
  program "/bin/ksh";
  command "myprog $HOME";

This flag is valid only for ‘inetd’ components. It has the same meaning as ‘wait’ in inetd.conf file, i.e. it tells pies to wait for the server program to return. See wait.


This is a TCPMUX component. See TCPMUX.


This is a TCPMUX+ component. See TCPMUX.


This is an internal inetd component. See builtin.


This inetd component wants socket description variables in its environment. See sockenv.


When used with ‘sockenv’, the LOCALHOST and REMOTEHOST environment variables will contain resolved host names, instead of IP addresses.


This flag affects the behavior of pies when a stopped process fails to terminate within a predefined timeout (see shutdown-timeout. Normally pies would send the ‘SIGKILL’ signal to such a process. If this flag is set, pies would send ‘SIGKILL’ to the process group of this process instead.

The following subsections describe the rest of ‘component’ substatements.

3.2.1 Component Prerequisites

Prerequisites (see component prerequisite) for a component are declared using the following statement:

Config: component: prerequisites tag-list

The argument is either a list of component tags, defined before this component, or one of the following words:


Declare all components defined so far as prerequisites for this one.


No prerequisites. This is the default.

If you wish, you can define dependents, instead of prerequisites:

Config: component: dependents tag-list

Declare dependents for this component. var-list is a list of component tags.

3.2.2 Component Privileges

The following statements control privileges the component is executed with.

Config: component: user user-name

Start component with the UID and GID of this user.

Config: component: group group-list

Retain supplementary groups, specified in group-list.

Config: component: allgroups bool

Retain all supplementary groups of which the user (as given with user statement) is a member. This is the default for components specified in meta1.conf file (see include-meta1).

3.2.3 Resources

Config: component: limits string

Impose limits on system resources, as defined by string. The argument consists of commands, optionally separated by any amount of whitespace. A command is a single command letter followed by a number, that specifies the limit. The command letters are case-insensitive and coincide with those used by the shell ulimit utility:

CommandThe limit it sets
Amax address space (KB)
Cmax core file size (KB)
Dmax data size (KB)
Fmaximum file size (KB)
Mmax locked-in-memory address space (KB)
Nmax number of open files
Rmax resident set size (KB)
Smax stack size (KB)
Tmax CPU time (MIN)
Umax number of processes
Pprocess priority -20..20 (negative = high priority)

Table 3.2: Limit Command Letters

For example:

limits T10 R20 U16 P20

Additionally, the command letter ‘L’ is recognized. It is reserved for future use (‘number of logins’ limit) and is ignored in version 1.4.

Config: component: umask number

Set the umask. The number must be an octal value not greater than ‘777’. The default umask is inherited at startup.

Config: component: max-instances n

Sets the maximum number of simultaneously running instances of this component.

3.2.4 Environment

Normally all components inherit the environment of the master pies process. You can modify this environment using the env statement. It has two variants: compound and legacy. The legacy one-line statement was used in pies versions up to 1.3 and is still retained for backward compatibility. It is described in env legacy syntax. This subsection describes the modern compount syntax.

Config: component: env { ... }

The compound env statement has the following syntax:

env {
   keep pattern;
   set "name=value";
   eval "value";
   unset pattern;

Statements inside the env block define operations that modify the environment. The clear and keep statements are executed first. Then, the set and unset statements are applied in the order of their appearance in the configuration.

env: clear

Clears the environment by removing (unsetting) all variables, except those listed in keep statements, if such are given (see below). The clear statement is always executed first.

env: keep pattern

Declares variables matching pattern (a globbing pattern) as exempt from clearing. This statement implies clear.

For example, the following configuration fragment removes from the environment all variables except ‘HOME’, ‘USER’, ‘PATH’, and variables beginning with ‘LC_’:

env {
  keep HOME;
  keep USER;
  keep PATH;
  keep "LC_*";
env: keep "name=value"

Retains the variable name, if it has the given value. Note, that the argument must be quoted.

env: set "name=value"

Assigns value to environment variable name. The value is subject to variable expansion using the same syntax as in shell. The set and unset (see below) statements are executed in order of their appearance. For example

env {
  set "MYLIB=$HOME/lib";
env: eval "value"

Perform variable expansion on value and discard the result. This is useful for side-effects. For example, to provide default value for the LD_LIBRARY_PATH variable, one may write:

env {
  eval "${LD_LIBRARY_PATH:=/usr/local/lib}";
env: unset pattern

Unset environment variables matching pattern. The following will unset the LOGIN variable:

unset LOGIN;

The following will unset all variables starting with ‘LD_’:

unset "LD_*";

Notice, that patterns containing wildcard characters must be quoted. env: legacy syntax.

Up to version 1.3 pies implemented the one-line variant of the env statement. The use of this legacy syntax is discouraged. It is supported for backward compatibility only and will be removed in future versions. This subsection describes the legacy syntax.

legacy syntax: env args

Set program environment.

Arguments are a whitespace-delimited list of specifiers. The following specifiers are understood:

- (a dash)

Clear the environment. This is understood only when used as a first word in args.

The modern syntax equivalent is:

env {

Unset the environment variable name. The modern syntax equivalent is

env {
  unset name;

Unset the environment variable name only if its value is val. The modern syntax equivalent is:

env {
  unset "name=val";

Retain the environment variable name. The modern syntax equivalent is

env {
  keep name;

Define environment variable name to have given value. The modern syntax equivalent is:

env {
  keep "name=value";

Retain variable name and append value to its existing value. If no such variable is present in the environment, it is created and value is assigned to it. However, if value begins with a punctuation character, this character is removed from it before the assignment. This is convenient for using this construct with environment variables like PATH, e.g.:


In this example, if PATH exists, ‘:/sbin’ will be appended to it. Otherwise, it will be created and ‘/sbin’ will be assigned to it.

In modern syntax, use shell variable references, e.g.:

env {
  set "PATH=${PATH}${PATH:+:}/sbin";

Retain variable name and prepend value to its existing value. If no such variable is present in the environment, it is created and value is assigned to it. However, if value ends with a punctuation character, this character is removed from it before assignment.

In modern syntax, use shell variable references, e.g. instead of doing

env PATH=+/sbin:


env {
  set "PATH=/sbin${PATH:+:}$PATH";

3.2.5 Actions Before Startup

The statements described in this subsection specify actions to perform immediately before starting the component:

Config: component: chdir dir

Change to the directory dir.

Config: component: remove-file file-name

Remove file-name. This is useful, for example, to remove stale UNIX sockets or pid-files, which may otherwise prevent the component from starting normally.

As of version 1.4 only one remove-file may be given.

Config: component: pass-fd-timeout number

Wait number of seconds for the ‘pass-fd’ socket to become available (see Meta1-Style Components). Default is 5 seconds.

3.2.6 Exit Actions

The default behavior of pies when a ‘respawn’ component terminates is to restart it. Unless the component terminates with 0 exit code, a corresponding error message is issued to the log file. This behavior can be modified using return-code statement:

Config: component: return-code
return-code codes {

The codes argument is a list of exit codes or signal names. Exit codes can be specified either as decimal numbers or as symbolic code names from the table below:

NameNumeric value

Table 3.3: Standard Exit Codes

Signal numbers can be given either as ‘SIG+n’, where n is the signal number, or as signal names from the following list: ‘SIGHUP’, ‘SIGINT’, ‘SIGQUIT’, ‘SIGILL’, ‘SIGTRAP’, ‘SIGABRT’, ‘SIGIOT’, ‘SIGBUS’, ‘SIGFPE’, ‘SIGKILL’, ‘SIGUSR1’, ‘SIGSEGV’, ‘SIGUSR2’, ‘SIGPIPE’, ‘SIGALRM’, ‘SIGTERM’, ‘SIGSTKFLT’, ‘SIGCHLD’, ‘SIGCONT’, ‘SIGSTOP’, ‘SIGTSTP’, ‘SIGTTIN’, ‘SIGTTOU’, ‘SIGURG’, ‘SIGXCPU’, ‘SIGXFSZ’, ‘SIGVTALRM’, ‘SIGPROF’, ‘SIGWINCH’, ‘SIGPOLL’, ‘SIGIO’, ‘SIGPWR’, ‘SIGSYS’.

If the component exits with an exit code listed in codes or is terminated on a signal listed in codes, pies executes actions specified in that ‘return-code’ block. The actions are executed in the order of their appearance below:

Config: return-code: exec command

Execute the supplied external command. Prior to execution, all file descriptors are closed. The command inherits the environment from the main pies process with the following additional variables:


The pies version number (1.4).


PID of the master pies process.


Tag of the terminated component (see tag).


PID of the terminated component.


If the component terminated on signal, the number of that signal.


Program exit code.

Config: return-code: action disable | restart

If ‘restart’ is given, restart the component. This is the default. Otherwise, mark the component as disabled. Component dependents are stopped and marked as disabled as well. Once disabled, the components are never restarted, unless their restart is requested by the administrator.

Config: return-code: notify email-string

Send an email notification to addresses in email-string. See Notification, for a detailed discussion of this feature.

Config: return-code: message string

Supply notification message text to use by notify statement. See Notification, for a detailed discussion of this feature.

Any number of return-code statements are allowed, provided that their codes do not intersect.

The return-code statements can also be used outside of component block. In this case, they supply global actions, i.e. actions applicable to all components. Any return-code statements appearing within a component block override the global ones.

3.2.7 Output Redirectors

Output redirectors allow to redirect the standard error and/or standard output of a component to a file or syslog facility.

Config: component: stderr type channel
Config: component: stdout type channel

Redirect standard error (if stderr) or standard output (if stdout) to the given channel.

The type of redirection is specified by type argument:


Redirect to a file. In this case channel gives the full name of the file. For example:

stderr file /var/log/component/name.err;

Redirect to a syslog channel. The syslog priority is given by the channel argument. Allowed values are: ‘emerg’, ‘alert’, ‘crit’, ‘err’, ‘warning’, ‘notice’, ‘info’, ‘debug’. The facility is inherited from the syslog statement (see syslog), or from the facility statement (see below), if given.


stderr syslog err;
Config: component: facility syslog-facility

Specify the syslog facility to use in syslog redirectors. Allowed syslog-facility values are: ‘user’, ‘daemon’, ‘auth’, ‘authpriv’, ‘mail’, ‘cron’, ‘local0’ through ‘local7’ (all names case-insensitive), or a facility number.

3.2.8 Inetd-Style Components

Inetd-style components are declared using mode inetd statement. The ‘component’ declaration must contain a ‘socket’ statement:

Config: component: socket url

Define a socket to listen on. Allowed values for url are:


Listen on IPv42 address ip (may be given as a symbolic host name), on port port. Optional proto defines the protocol to use. It must be a valid protocol name as given in /etc/protocols. Default is ‘tcp’.


Listen on the UNIX socket file file, which is either an absolute or relative file name, as described above. The proto part is as described above. Optional arguments, args, control ownership and file mode of file. They are a list of assignments, separated by semicolons. The following values are allowed:


User name of the socket owner.


Owner group of the socket, if it differs from the user group.


Socket file mode (octal number between ‘0’ and ‘777’).


Umask to use when creating the socket (octal number between ‘0’ and ‘777’).

For example:


The file part may be a relative file name, provided that the chdir statement is used for this component (see chdir).

Config: component: socket-type type

Sets the socket type. Allowed values for type are: ‘stream’, ‘dgram’, ‘raw’, ‘rdm’, ‘seqpacket’. Default is ‘stream’. Notice that some socket types may not be implemented by all protocol families, e.g. ‘seqpacket’ is not implemented for ‘inet’.

Config: component: max-rate n

Specifies the maximum number of times the component can be invoked in one minute; the default is unlimited. A rate of ‘0’ stands for ‘unlimited’.

Config: component: max-instances n

Sets the maximum number of simultaneously running instances of this component. It is equivalent to the maximum number of simultaneously opened connections.

Config: component: max-instances-message text

Text to send back if max-instances is reached. This is valid only for TCP sockets.

Config: component: max-ip-connections number

Maximum number of connections that can be opened simultaneously from a single IP address.

Config: component: max-ip-connections-message text

Textual message to send in reply to an incoming TCP connection from the IP address that has already reached max-ip-connections limit.

Config: component: acl { … }

Set access control list for this component. This is valid only for ‘inetd’ and ‘accept’ components. See ACL, for a detailed description of access control lists.

Config: component: access-denied-message text

Textual message to send in reply to an incoming TCP connection that has been denied by ACL settings. Built-in Inetd Services

Built-in or internal services are such inetd-style components that are supported internally by pies and do not require external programs. In pies version 1.4 those are:


Send back any received data. Defined in RFC 862.


Read the data and discard them. Defined in RFC 863.


Return a machine readable date and time as seconds since the Epoch. Defined in RFC 868.


Return current date and time in human-readable format. Defined in RFC 867.


Send a continuous stream of ASCII printable characters without regard to the input. Defined in RFC 864


Send a ‘quotation of the day’ text without regard to the input. Defined in RFC 865.


TCP Port Service Multiplexer. Defined in RFC 1078.

A definition of a built-in service component must have the internal flag (see flags) set. It may not contain command or program statements, as built-in services do not need external programs. Instead, a service declaration must be present:

Config: component: service name

Set the built-in service name. Its argument is one of the keywords listed in the above table.

For example, the following component declaration defines a standard TCP-based echo service:

component echo {
        socket "inet://";
        service echo;
        flags internal;

It corresponds to the following inetd.conf line:

echo stream  tcp     nowait  root    internal

Another built-in services are defined in the same manner, replacing ‘echo’ in the service field with the corresponding service name.

The ‘qotd’ service reads the contents of the qotd file and sends it back to the client. By default the ‘qotd’ file is located in the local state directory and named instance.qotd (where instance is the name of the pies instance; see instances). This default location can be changed using the following statement:

Config: qotd-file file-name

Set the name of the ‘quotation-of-the-day’ file.

The text read from the ‘qotd’ file is preprocessed, by replacing each LF character (ASCII 10) with two characters: CR (ASCII 13) followed by LF. The resulting text is truncated to 512 characters.

The use of ‘tcpmux’ services is covered below. TCPMUX Services

TCPMUX allows to use multiple services on a single well-known TCP port using a service name instead of a well-known number. It is defined in RFC 1078. The protocol operation is as follows. The master TCPMUX component listens on a certain TCP port (usually on port 1) for incoming requests. After connecting to the master, the client sends the name of the service it wants, followed by a carriage-return line-feed (CRLF). Pies looks up this name in the list of services handled by the master (subordinate services) and reports with ‘+’ or ‘-’ followed by optional text and terminated with the CRLF, depending on whether such service name is found or not. If the reply was ‘+’, pies then starts the requested component. Otherwise, it closes the connection.

TCPMUX service names are case-insensitive. The special service ‘help’ is always defined; it outputs a list of all the subordinate services, one name per line, and closes the connection.

The master TCPMUX service is declared as a usual built-in service, e.g.:

component tcpmux-master {
        socket "inet://";
        service tcpmux;
        flags internal;

Any number of subordinate services may be defined for each master. A subordinate server component definition must contain at least the following statements:

Config: component: service name

Sets the name of the subordinate service. The name will be compared with the first input line from the client.

Config: component: tcpmux-master name

Sets the name of the master TCPMUX service.

Config: component: flags list

The flags statement (see flags) must contain at least one of the following flags:


A “dedicated” TCPMUX subordinate service. When invoked, it must output the ‘+ CRLF’ response itself.


Simple service. Before starting it, pies will send the ‘+ CRLF’ reply.

Config: component: command command-line

The command line for handling this service.

For example:

component scp-to {
        service scp-to;
        flags (tcpmuxplus, sockenv);
        tcpmux-master tcpmux;
        command "/usr/sbin/in.wydawca";

For TCPMUX services, access control lists are handled in the following order. First, the global ACL is checked. If it rejects the connection, no further checks are done. Then, if the master TCPMUX service has an ACL, that ACL is consulted. If it allows the connection, the subordinate is looked up. If found, its ACL (if any) is consulted. Only if all three ACLs allow the connection, is the service started.

A similar procedure applies for other resources, such as limits, umask, env, user, group, etc. Socket Environment Variables

If the ‘sockenv’ flag is set (see sockenv), the following environment variables are set prior to executing the command:


Protocol name.


Socket type. See socket-type, for a list of possible values.


IP address of the server which is handling the connection.


Local port number.


Host name of the server. This variable is defined only if the ‘resolve’ flag is set (see resolve).


IP address of the remote party (client).


Port number on the remote side.


Host name of the client. This variable is defined only if the ‘resolve’ flag is set (see resolve).

The variables whose names begin with REMOTE are defined only for TCP connections. Exit Actions in Inetd Components

Exit actions (see Exit Actions) work for ‘inet-style’ components. The only difference from ‘respawn’ components is that the ‘restart’ action is essentially ignored, as it makes no sense to start an ‘inet-style’ component without a communication socket.

A common use of return-code statement is to invoke an external program upon the termination of a component. For example, the following configuration snippet configures an FTP server and ensures that a special program is invoked after closing each FTP connection:

component ftp {
    return-code EX_OK {
        exec "/sbin/sweeper --log";
    mode inetd;
    socket "inet://";
    umask 027;
    program /usr/sbin/in.ftpd
    command "ftpd -ll -C -t180";

This approach may be used to process FTP uploads in real time.

3.2.9 Meta1-Style Components

Meta1-style components are declared using mode pass statement. For such components, you must declare both a socket to listen on (see inetd-socket and a UNIX socket name to pass the file descriptor to the component. The latter is defined using pass-fd-socket statement:

Config: component: pass-fd-socket file-name

The argument is an absolute or relative file name of the socket file. In the latter case, the chdir dir statement must be used for this component (see chdir), and the socket will be looked under dir.

This socket file is supposed to be created by the component binary upon its startup.

3.2.10 Component Visibility ACLs

Pies control interface allows certain users to list and modify components of a running pies instance. Two access control lists define who can list and modify the particular component.

Config: component: list-acl name
Config: component: list-acl { … }

This list controls who can get listing of this component (see piesctl list).

In the first form, name refers to the name of an already defined global ACL (see defacl).

The second form defines new unnamed ACL. The syntax is described in detail in ACL.

Config: component: admin-acl name
Config: component: admin-acl { … }

This list controls who can stop, restart or otherwise modify this component (see components).

As above, two forms are available: the first one for using an already defined named ACL, and the second one, for defining a new ACL in place.

3.2.11 Component Syntax Summary

This subsection summarizes the component statements. For each statement, a reference to its detailed description is provided.

component tag {
  # Component execution mode.
  # See mode.
  mode ‘exec | wait | accept | inetd | nostartaccept | pass-fd | pass’;
  # Full name of the program.
  # See program.
  program name;
  # Command line.
  # See command.
  command string;
  # List of prerequisites.
  # See Prerequisites.
  prerequisites (compnames);
  # List of components for which this one is a prerequisite.
  # See dependents.
  dependents (compnames);

  # List of flags.
  # See flags.
  flags (flags);

  # For init components: runlevels in which to start this
  # component.
  # See Runlevels.
  runlevels string;
  # Listen on the given url.
  # See Inetd-Style Components.
  socket url;

  # Set socket type.
  # See Inetd-Style Components.
  socket-type ‘stream | dgram | raw | rdm | seqpacket’;

  # Service name for built-in inetd component.
  # See builtin.
  service string;

  # Tag of master TCPMUX component, for subordinate components.
  # See TCPMUX.
  tcpmux-master string;
  # Pass fd through this socket.
  # See Meta1-Style Components.
  pass-fd-socket soket-name;
  # Wait number of seconds for pass-fd socket to become available.
  # See pass-fd-timeout.
  pass-fd-timeout number;

  # Maximum number of running instances.
  # See max-instances.
  # See max-instances.
  max-instances number;

  # For ‘inetd’ components:
  # Text to send back if max-instances is reached.
  # See max-instances-message.
  max-instances-message text;
  # Maximum number of times an inetd component can be invoked in
  # one minute.
  # See max-rate.
  max-rate number;

  # For ‘inetd’ components:
  # Max. number of simultaneous connections from a single IP address.
  # See max-ip-connections.
  max-ip-connections number;
  # For ‘inetd’ components:
  # Text to send back if max-ip-connections is reached.
  # See max-ip-connections-message.
  max-ip-connections-message text;

  # For ‘inetd’ components:
  # Text to send back if access is denied by ACL.
  # See access-denied-message.
  access-denied-message text;

  # ACL for administrative (read-write) access to this component.
  # See Visibility.
  admin-acl name;
  # or:
  admin-acl { … }

  # ACL for read-only access to this component.
  # See Visibility.
  list-acl name;
  # or:
  list-acl { … }
  # ACL for this component.
  # See ACL.
  acl name;
  # or:
  acl { … }
  # Override default syslog facility for this component.
  facility facility;
  # Redirect program’s standard output to the given
  # file or syslog priority.
  # See Output Redirectors.
  stdout ‘file | syslogchannel;
  # Redirect program’s standard error to the given
  # file or syslog priority.
  # See Output Redirectors.
  stderr ‘file | syslogchannel;
  # Run with this user privileges.
  # See Component Privileges.
  user user-name;
  # Retain supplementary group.
  # See group.
  group group-name;
  # Retain all supplementary groups of which user is a member.
  # See allgroups.
  allgroups bool;
  # Set system limits.
  # See Resources.
  limits string;
  # Force this umask.
  # See umask.
  umask number;
  # Set program environment.
  # See env.
  env assignments;
  # Change to this directory before executing the component.
  # See chdir.
  chdir dir;
  # Remove file-name before starting the component.
  # See remove-file.
  remove-file file-name;
  # Actions:
  # See Exit Actions.
  return-code exit-code-list {
    # Action to take when a component finishes with this return code.
    action ‘disable | restart’;
    # Notify these addresses when then component terminates.
    notify email-string;
    # Notification message text (with headers).
    message string;
    # Execute this command.
    exec command

3.3 Notification

Pies provides a notification mechanism, which can be used to send email messages when components terminate. The exact contents of such notifications and the list of their recipients may depend on the exit code which the component returned. Notification is configured by ‘notify’ and ‘message’ statements in a ‘return-code’ block.

Config: return-code: notify email-string

Send email notification to each address from email-string. The latter is a comma-separated list of email addresses, e.g.:

notify "root@localhost,postmaster@localhost";
Config: return-code: message string

Supply the email message text to be sent. String must be a valid RFC 822 message, i.e. it must begin with message headers, followed by an empty line and the actual message body.

The message may contain variable data in the form of variable references. A variable is an entity that holds some data describing the event that occurred. Meta-variables are referenced using the following construct:


where name is the name of the variable. Before actually sending the message, each occurrence of this construct is removed from the text and replaced by the actual value of the referenced variable. For example, the variables ‘component’ and ‘retcode’ expand to the name of the exited component and its exit code, correspondingly. Supposing that ‘component’ is ‘ftpd’ and ‘retcode’ is 76, the following fragment:

Subject: ${component} exited with code ${retcode}

will become:

Subject: ftpd exited with code 76

The table below lists all available variables and their expansions:

program_nameProgram name of the pies binary.
packagePackage name (‘GNU Pies’).
instanceInstance name (see instances).
versionPackage version (1.4).
componentName of the terminated component.
terminationTermination cause (see below).
retcodeComponent exit code (or signal number, if exited on signal), in decimal.

Table 3.4: Notification Variables

The ‘termination’ variable is set so as to facilitate its use with the ‘retcode’ variable. Namely, its value is ‘exited with’, if the component exited and ‘terminated on signal’, if it terminated on a signal. Thus, using

${termination} ${retcode}

results in a correct English sentence. This message, however, cannot be properly internationalized. This will be fixed in the future versions.

If message statement is not given, the following default message is used instead:

From: <>
X-Agent: ${canonical_program_name} (${package} ${version})
Subject: Component ${component} ${termination} ${retcode}.

Notification messages are sent using an external program, called mailer. By default it is /usr/sbin/sendmail. You can change it using the following configuration statement:

Config: mailer-program prog

Use prog as a mailer program. The mailer must meet the following requirements:

  1. It must read the message from its standard input.
  2. It must treat the non-optional arguments in its command line as recipient addresses.

For example, the following statement instructs pies to use exim as a mailer:

mailer-program /usr/sbin/exim;

By default, the mailer program is invoked as follows:

/usr/sbin/sendmail -oi -t rcpts

where rcpts is a whitespace-separated list of addresses supplied in the ‘notify’ statement.

The mailer command may be altered using ‘mailer-command-line’ statement:

Config: mailer-command-line string

Set mailer command line. Notice, that string must include the command name as well. The ‘mailer-program’ statement supplies the full name of the binary which will be executed, while the first word from the ‘mailer-command-line’ argument gives the string it receives as ‘argv[0]’.

The example below shows how to use this statement to alter the envelope sender address:

mailer-command-line "sendmail -f -oi -t";

3.4 Access Control Lists

Access control lists, or ACLs for short, are lists of permissions that control access to ‘inetd’, ‘accept’ and ‘meta1’-style components.

An ACL is defined using acl block statement:

Config: acl
acl {

This statement is allowed both in global context and within a ‘component’ block. If both are present, the global-level ACL is consulted first, and if it allows access, the component ACL is consulted. As a result, access is granted only if both lists allow it.

A named ACL is an access control list which is assigned its own name. Named ACLs are defined using the ‘defacl’ statement:

Config: defacl name
defacl name {

The name parameter specifies a unique name for that ACL. Named ACLs are applied only if referenced from another ACL (either global or a per-component one, or any named ACL, referenced from these). See ACL references, below.

In both forms, the part between the curly braces (denoted by definitions), is a list of access control statements. There are two types of such statements:

Config: acl: allow [user-group] sub-acl host-list
Config: acl: allow any

Allow access to the component.

Config: acl: deny [user-group] sub-acl host-list
Config: acl: deny any

Deny access to the component.

All parts of an access statement are optional, but at least one of them must be present. The user-group part is reserved for future use and is described in more detail in User-Group ACLs.

The sub-acl part, if present, allows to branch to another ACL. The syntax of this part is:

acl name

where name is the name of an ACL defined previously in ‘defacl’ statement.

The host-list group allows to match client addresses. It consists of the from keyword followed by a list of address specifiers. Allowed address specifiers are:


Matches if the client IP equals addr. The latter may be given either as an IP address or as a host name, in which case it will be resolved and the first of its IP addresses will be used.


Matches if first netlen bits from the client IP address equal to addr. The network mask length, netlen, must be an integer number in the range from 0 to 32. The address part, addr, is as described above.


The specifier matches if the result of logical AND between the client IP address and netmask equals to addr. The network mask must be specified in “dotted quad” form, e.g. ‘’.


Matches if connection was received from a UNIX socket filename, which must be given as an absolute file name.

The special form ‘allow any’ means to allow access unconditionally. Similarly, ‘deny any’, denies access unconditionally. Normally, one of these forms appears as the last statement in an ACL definition.

To summarize, the syntax of an access statement is:

allow|deny [acl name] [from addr-list]

where square brackets denote optional parts.

When an ACL is checked, its entries are tried in turn until one of them matches, or the end of the list is reached. If a matched entry is found, its command verb, allow or deny, defines the result of the ACL check. If the end of the list is reached, the result is ‘allow’, unless explicitly specified otherwise (using the “any” form.)

For example, the following ACL allows access for anybody coming from networks ‘’ and ‘’, or any connection that matches the named ACLmy-nets’ (which is defined elsewhere in the configuration file). Access is denied for anybody else:

acl {
    allow from (,;
    allow acl "my-nets";
    deny all;

3.5 The Control Statement

The control interface provides a method for communication with the running pies instance. It is used by the piesctl utility to query information about the instance and components it is currently running and to send it commands for controlling its operation (see piesctl). By default the UNIX socket /tmp/pies.ctl is used for this purpose. If pies was started with the --instance=name option, the socket is named /tmp/name.ctl. Whatever its name, the socket will be owned by the user pies runs as (see Pies Privileges) and will have access rights of 0500, allowing only that user to read and write to it. When pies is used as init process, the default socket name is /dev/init.ctl.

Config: control

The ‘control’ statement configures the control interface and limits access to it:

control {
    socket url;
    acl { … }
    admin-acl { … }
    user-acl { … }
    realm name;
Config: control: socket url

URL of the control socket. The url argument is a string of the following syntax:


Listen on IPv4 address ip (may be given as a symbolic host name), on port port.


Listen on the UNIX socket file file, which is either an absolute or relative file name. Optional arguments args control ownership and file mode of file. They are a semicolon-separated list of assignments to the following variables:


User name of the socket owner.


Owner group of the socket, if it differs from the user group.


Socket file mode (octal number between ‘0’ and ‘777’).


Umask to use when creating the socket (octal number between ‘0’ and ‘777’).

Config: control: idle-timeout n

Disconnect any control session that remains inactive for n seconds. This statement is reserved for use in the future. Currently (as of version 1.4) it is a no-op.

The control interface is protected by three access control lists (See ACL, for a discussion of their syntax).

Config: control: acl name
Config: control: acl { … }

Controls who can connect to the interface. The first form refers to a named ACL that must have been defined earlier by defacl statement (see defacl). Use the second form to define a new ACL in place.

Config: control: user-acl name
Config: control: user-acl { … }

Control interface provides two kinds of operations: read-only (such as getting information about running components) and write operations (such as stopping or restarting components).

The user-acl controls read access. Access to particular components can also be controlled individually, using the per-component list-acl statement (see list-acl).

Config: control: admin-acl name
Config: control: admin-acl { … }

Controls write access to the pies instance itself and to the components for which no specific admin-acl statements are supplied (see admin-acl).

In particular, whoever passes admin-acl can issue commands for stopping the instance and reloading its configuration.

When checking whether the user has a particular kind of access to a component, first the corresponding ACL from the control section is checked. If it allows access, then the per-component ACL is tried. If it allows access too, then the operation is permitted.

Config: control: realm name

Defines the realm for basic authentication. Default value is ‘pies’.

3.6 User Identities for Accessing Control Interface

Privileges for using and performing various commands over the control interface can be distributed among several users. For example, it is possible to grant some users the rights to only view the component listing, or even to further limit their rights to only see the components they are authorized to know about. Another user may be able to stop or restart components and so on. This privilege separation requires pies to have a notion of user and be able to authenticate it.

Identity provider is an abstract mechanism that pies uses to obtain information about the user trying to authenticate himself for accessing a particular control function. As of version 1.4, this mechanism is considered experimental. That means, that although being fully functional, it can change considerably in future releases.

Identity provider supports two operations: authenticating a user, and checking if he is a member of particular group. It is defined in the configuration file using the identity provider statement.

Config: identity-provider name

Defines an identity provider. It is a block statement:

identity-provider name {
  type type;

The provider name is used in diagnostic messages.

The only required substatement is type, which defines the type of the provider. Rest of statements (represented by … above) depends on the type.

Pies version 1.4 supports identity providers of two types: ‘system’ and ‘pam’.

The ‘system’ identity provider uses system user database for authentication and system group database for checking group membership. It is declared using the following statement:

identity-provider name {
    type system;

Obviously, to use the system identity provider for authentication, pies must be run as root.

The ‘pam’ identity provider uses the Pluggable Authentication Modules (PAM) for authentication, and system group database for checking group membership.

identity-provider name {
    type pam;
    service srv;

The ‘service’ statement defines the name of PAM service to use for authentication. If absent, the name ‘pies’ is used.

Any number of different identity providers can be declared in the configuration file. When authenticating the user, they will be tried in turn until the one is found where authentication succeeds. Subsequent group membership checks will then use this identity provider.

3.7 Using inetd Configuration Files

In addition to its native configuration file format, GNU pies is able to read configuration files of several other widely-used utilities. One of these is inetd. The simplest way to use such configuration files is by including them to your main pies.conf using the include-inetd statement:

Config: include-inetd file

Read components from inetd-style configuration file file. The argument may also be a directory, in which case all regular files from that directory are read and parsed as inetd-style configuration files.

The components read from file are appended to the pies list of components in order of their appearance.

For example, the following statement reads components from the standard inetd configuration file:

include-inetd /etc/inetd.conf;

Any number of include-inetd may be specified. For example, the following reads the contents of the /etc/inetd.conf configuration file and all files from the /etc/inetd.d directory:

include-inetd /etc/inetd.conf;
include-inetd /etc/inetd.d;

Another way to read inetd configuration files is to supply them in the command line, like this:

pies --syntax=inetd --config-file /etc/inetd.conf

Notice the --syntax option (see config syntax). It informs pies that the following files are in inetd format. Of course, several configuration file may be given:

pies --syntax=inetd \
     --config-file /etc/inetd.conf --config-file /etc/inetd.d

A special option is provided that instructs pies to behave as inetd:


Read configuration from sysconfdir/inetd.conf and make sure pies state files (see State Files) do not conflict with those from other pies instances.

The GNU Pies package also provides a wrapper that allows to use pies instead of inetd. It is built if the package is configured with the --enable-inetd option. The wrapper is then installed in sbindir as inetd, possibly replacing the system binary of that name.

The command line usage of the inetd wrapper is entirely compatible with that of the usual inetd utility, i.e.:

inetd [option] [config [config...]] [-- pies-options]

Options are:


Increase debug level.

-R rate

Set maximum rate (see max-rate).

For convenience, the following additional options are understood:


Parse configuration file or files and exit. See lint.


Display info about the running instance. See pies-status.


Stop the running instance.

Finally, any additional options pies understands may be given to inetd after the ‘--’ separator.

3.8 Using MeTA1 Configuration File

MeTA1 is a mail transfer agent of new generation, designed to replace Sendmail in the future ( It has a modular structure, each module being a component responsible for a particular task. The components are configured in the MeTA1 configuration file /etc/meta1/meta1.conf.

Pies can take a list of components directly from MeTA1 configuration file:

Config: include-meta1 file

Parse file as MeTA1 configuration file and incorporate components defined there into the current component list.

For example:

include-meta1 /etc/meta1/meta1.conf;

Thus, you can use pies instead of the default MeTA1 program manager mcp. This is particularly useful if you use ‘Mailfromd’ ( to control the mail flow.

To ensure compatibility with MeTA1, the components read from its configuration file are started in the reverse order (i.e. from last to first), and stopped in the order of their appearance in file.

The following pies statements are silently applied to all MeTA1 components:

allgroups yes;
stderr file compname.log
chdir queue-dir

Here, compname stands for the name of the component, and queue-dir stands for the name of MeTA1 queue directory. The latter is /var/spool/meta1 by default. It can be changed using the following statement:

Config: meta1-queue-dir dir

Set name of MeTA1 queue directory.

To override any default settings for a MeTA1 component, add a command section with the desired settings after including meta1.conf. For example, here is how to redirect the standard error of the ‘smtps’ component to ‘local1.debug’ syslog channel:

include-meta1 /etc/meta1/meta1.conf

component smtps {
  facility local1;
  stderr syslog debug;

3.9 Global Configuration

The statements described in this section affect pies behavior as a whole.

Config: syslog { … }

This block statement configures logging via syslog. It has two substatements:

Config: syslog: tag string

Prefix syslog messages with this string. By default, the program name is used.

Config: syslog: facility string

Set syslog facility to use. Allowed values are: ‘user’, ‘daemon’, ‘auth’, ‘authpriv’, ‘mail’, ‘cron’, ‘local0’ through ‘local7’ (case-insensitive), or a facility number.

Config: umask number

Set the default umask. The number must be an octal value not greater than ‘777’. The default umask is inherited at startup.

Config: limits arg

Set global system limits for all pies components. See limits, for a detailed description of arg.

Config: return-code { … }

Configure global exit actions. See Exit Actions, for a detailed description of this statement.

Config: shutdown-timeout number;

Wait number of seconds for all components to shut down. Default is 5 seconds.

The normal shutdown sequence looks as follows:

  1. Send all components the SIGTERM signal.
  2. Wait at most shutdown-timeout seconds for their termination.

    If any components are still running at the end of this interval:

    1. Send all components the SIGKILL signal.
    2. Wait at most shutdown-timeout seconds for their termination.

If any shutdown components are defined, start them and wait for their termination. If any components are left running after shutdown-timeout seconds, terminate them using the above procedure.

This means that pies termination sequence can take up to 5*shutdown-timeout seconds.

3.10 Pies Privileges

Normally, pies is run with root privileges. If, however, you found such an implementation for it, that requires another privileges, you may change them using the following three statements:

Config: user user-name

Start pies with the UID and GID of this user.

Config: group group-list

Retain the supplementary groups, specified in group-list.

Config: allgroups bool

Retain all supplementary groups the user (as given with user statement) is a member of.

An example of such implementation is using pies to start jabberd components:

3.11 State Files

Pies uses several files to keep its state information. The directory which hosts these files is called state directory, it is usually /var/pies or /usr/local/var/pies). The state directory can be configured at run time:

Config: state-directory dir

Set the program state directory.

The table below describes the files kept in the state directory. The instance in this table stands for the pies instance name (see instances). Usually, it is ‘pies’.

The PID file. It keeps the PID number of the running pies instance.


The Quotation-of-the-day file. It is used by the ‘qotd’ built-in service (see qotd).

The following statements allow to redefine state file names. Use them only if the defaults do not suit your needs, and neither the state-directory statement nor the --instance option can help:

Config: pidfile file

Sets the PID file name.

Config: qotd-file file-name

Sets the name of the ‘quotation-of-the-day’ file.

The following statements are retained for compatibility with earlier pies versions. They are silently ignored:

Config: control-file arg
Config: stat-file arg



Support for IPv6 will be added in future versions.

GNU Pies Manual (split by chapter):   Section:   Chapter:FastBack: Configuration   Up: Configuration   FastForward: Pies Debugging   Contents: Table of ContentsIndex: Concept Index