@c This is part of the GNU Pies manual.
@c Copyright (C) 2009--2025 Sergey Poznyakoff
@c This file is distributed under GFDL 1.3 or any later version
@c published by the Free Software Foundation.

  This appendix describes @dfn{control API} used to communicate with the
running @command{pies} daemon via the control interface
(@pxref{control}).  This API is used by @command{piesctl} (@pxref{piesctl}).

The API is designed as a REST service and uses HTTP.  Queries are sent to
pies @dfn{endpoints}, each of which serves a distinct purpose.  Data
are serialized using the JSON format.

The sections below describe in detail each endpoint and associated
with it request types.

@node /instance
@appendixsec /instance
  This endpoint controls the state of the running @command{pies}
instance and accepts the following HTTP requests: @code{GET},
@code{DELETE}, @code{POST} (or @code{PUT}).

@deffn {Request} GET /instance
  Retrieves information about the current instance.  The response body
is a JSON object with the following attributes:

@table @samp
@item PID
PID of the running daemon.

@item argv
Array of the command line arguments.  @samp{argv[0]} is the program
name.

@item binary
Name of the @command{pies} binary.

@item instance
The instance name.  @xref{instances}.

@item package
Package name (the string @samp{GNU Pies}).

@item version
Package version
@end table

Any of these can be used in the URI to request the information about
that particular attribute, e.g.:

@example
GET /instance/argv @result{} @{"argv":["pies", "-x2"]@}
@end example
@end deffn

@deffn {Request} DELETE /instance/PID
Stops the current @command{pies} instance.
@end deffn

@deffn {Request} PUT /instance/PID
@deffnx {Request} POST /instance/PID
Restarts the current @command{pies} instance.
@end deffn

@node /conf
@appendixsec /conf

The @samp{/conf} endpoint allows the client to inspect and change the
configuration of the running @command{pies} instance.

@node /conf/files
@appendixsubsec /conf/files

@deffn {Request} GET /conf/files
Return list of configuration files.  On success, a JSON array is
returned.  Each array element is an object with two attributes:

@defvr {Attr} string file
Pathname of the configuration file.
@end defvr

@defvr {Attr} string syntax
Configuration file syntax (@pxref{Syntax}).
@end defvr

For example:

@example
GET /conf/files @result{}
[@{"file":"/etc/pies.conf", "syntax":"pies"@},
 @{"file":"/etc/inetd.conf", "syntax":"inetd"@}]
@end example
@end deffn

@deffn {Request} POST /conf/files
Adds a new configuration file.   The body must be a JSON object with
@samp{file} and @samp{syntax} attributes, as described above.  The
@samp{file} value must contain a pathname of a configuration file
written in a syntax supplied by the @samp{syntax} attribute
(@pxref{Syntax}).

This request returns 201 code on success.  To actually parse and load
the added configuration file, send a @samp{PUT} request to
@samp{/conf/runtime} (@pxref{/conf/runtime}).
@end deffn

@deffn {Request} DELETE /conf/files/true
Clears all previously configured configuration files.  Responds with:

@example
@{ "message":"file list cleared", "status":"OK" @}
@end example
@end deffn

@deffn {Request} DELETE /conf/files/[@var{list}]
Removes files named in the @var{list} from the list of configuration files.

The @samp{DELETE} response is 200 on success.  To actually update the
configuration of the running process, send a @samp{PUT} request to
@samp{/conf/runtime} (@pxref{/conf/runtime}).
@end deffn

@node /conf/runtime
@appendixsubsec /conf/runime

This is a write-only URI.  The only request supported is
@samp{PUT /conf/runtime}.  It initiates reloading of the
@command{pies} configuration.  Usually, this request is sent after one
or more @samp{POST} and/or @samp{DELETE} requests to
@samp{/conf/files}, in order to finalize the changes applied to the
configuration.

@node /programs
@appendixsec /programs

  A request sent to this URI selects one or more components and
applies operation defined by the request type to all of them.

  Components are selected using a query in the form of JSON object
(a @dfn{selector}).  Valid selectors are:  

@table @samp
@item null
@itemx false
Matches nothing.

@item true
Matches all components.

@item @{ "op": "component", "arg": @var{tag} @}
Matches component with the given @var{tag} (@pxref{tag}).

@item @{ "op": "type", "arg": "component" @}
Matches all components.

@item @{ "op": "type", "arg": "command" @}
Matches all commands.

@item @{ "op": "mode", "arg": @var{mode} @}
Matches all components with the given @var{mode}.  @xref{component
mode}.

@item @{ "op": "active" @}
Matches all active components.

@item @{ "op": "status", "arg": @var{status} @}
Matches all components with the given @var{status} (one of
@samp{stopped}, @samp{running}, @samp{listener}, @samp{sleeping},
@samp{stopping}, @samp{finished}).  @xref{component status} for a
discussion of these values.

@item @{ "op: "not", "arg": @var{condition} @}
Negates @var{condition}, which is any valid selector.

@item @{ "op": "and", "arg": @var{array} @}
Returns the result of logical conjunction on the @var{array} of selectors.

@item @{ "op": "or", "arg": @var{array} @}
Returns the result of logical disjunction on the @var{array} of selectors.
@end table

  For example, the following selector matches all components that are
in @samp{running} state, excepting components of @samp{inetd} mode:

@example
@{ "op": "and",
   "arg": [ @{ "op": "type", "arg": "component" @},
            @{ "op": "not", "arg": @{ "op": "mode", "arg": "inetd" @}
          ]
@}
@end example

The following requests are supported:

@deffn {Request} GET /programs?@var{selector}
@deffnx {Request} GET /programs/@var{tag}
  This request returns information about components matched by
@var{selector} (see below for the @samp{/programs/@var{tag} variant}.
The response is a JSON array of descriptions.  If no component matches
the @var{selector}, empty array is returned.  Each description is a
JSON object with the following attributes:

@deftypevr {Attr} string type
Type of the described entity: @samp{component} for an instance of a
configured component, and @samp{command} for a command run as a part
of exit action (@pxref{Exit Actions}), including mailer invocations
(@pxref{Notification}).
@end deftypevr

@deftypevr {Attr} string mode
Mode of the entity.  @xref{component mode}.
@end deftypevr

@anchor{component status}
@deftypevr {Attr} string status
Entity status.   Possible values are:

@table @code
@item finished
A @samp{once} or @samp{startup} component has finished.

@item listener
Component is an inetd listener.

@item running
Component is running.

@item sleeping
Component has been put to sleep because of excessive number of
failures (@pxref{respawn}).

@item stopped
Component is stopped.

@item stopping
Component is being stopped (a @code{SIGTERM} was sent).
@end table
@end deftypevr

@deftypevr {Attr} boolean active
Whether this component is active.  By default, all components are
active, unless marked with a @samp{disable} flag (@pxref{flags}) or
administratively stopped.
@end deftypevr

@deftypevr {Attr} integer PID
PID of the running process.
@end deftypevr

@deftypevr {Attr} string URL
(for @samp{inetd} components) URL of the socket the component is
listening on.
@end deftypevr

@deftypevr {Attr} string service
(for @samp{tcpmux} components) TCPMUX service name.  @xref{TCPMUX}.
@end deftypevr

@deftypevr {Attr} string master
(for @samp{tcpmux} components) Tag of master TCPMUX component.
@xref{TCPMUX}.
@end deftypevr

@deftypevr {Attr} string runlevels
For inittab components, the string of runlevels this component is
configured to run in.  @xref{Init Process}.
@end deftypevr

@deftypevr {Attr} integer wakeup-time
If component is in the @samp{sleeping} state, this attribute gives the
number of seconds after which an attempt will be made to restart it.
@end deftypevr

@deftypevr {Attr} array argv
Component command line split into words.
@end deftypevr

@deftypevr {Attr} string command
Component command.
@end deftypevr
@end deffn

@deffn {Request} DELETE /programs?@var{selector}
@deffnx {Request} DELETE /programs/@var{tag}
Stop components matched by the @var{selector}.  On success returns:

@example
@{ "status":"OK" @}
@end example

@noindent
On failure, returns

@example
@{ "status":"ER", "message": @var{text} @}
@end example

@noindent
where @var{text} is a textual human-readable description of the failure.
@end deffn

@deffn {Request} PUT /programs?@var{selector}
@deffnx {Request} PUT /programs/@var{tag}
Start components matched by @var{selector}.
@end deffn

@deffn {Request} POST /programs
Restart components.  The selector is supplied in the request content.
@end deffn

Wherever a selector is passed via query parameters, a simplified form
with component tag passed as query path is also allowed.  For example:

@example
 GET /programs/@var{tag}
@end example

@noindent
is a shortcut for:

@example
@{ "op":"and",
   "arg":[ @{"op":"type", "arg":"component"@},
           @{"op":"component", "arg":@var{tag} @} ] @}
@end example

@node /alive
@appendixsec /alive

  This entry point accepts only @samp{GET} requests.  The URI must not
be empty and must not include sub-directories (parts separated with
slashes).  It is treated as the name of the component to return the
status of.  E.g. querying @samp{/alive/foo} returns the status of the
component named @samp{foo}.  The status is returned as HTTP status
code:

@table @asis
@item 200
The component is up and running.  For regular components that means
that the corresponding program is running.  For @samp{inetd}
components that means that the listener is listening on the configured
socket.

@item 403
No component specified.

@item 404
There is no such component.

@item 503
The component is not running.  This means that it has failed, or has
been stopped administratively or (for @samp{once} and @samp{startup}
components) that it has run once and finished.

If the component has failed, the @samp{Retry-After:} HTTP header
contains the number of seconds after which @command{pies} will retry
starting this component.
@end table

@node /runlevel
@appendixsec /runlevel
  This URI is active when @command{pies} runs as init process
(@pxref{Init Process}).  It supports two requests:

@deffn {Request} GET /runlevel
Returns the current state of the program as a JSON object with the
following attributes:

@defvr {Attr} string runlevel
Current runlevel.  @xref{Runlevels}.
@end defvr

@defvr {Attr} string prevlevel
Previous runlevel (@samp{N} if none).
@end defvr

@defvr {Attr} string bootstate
Boot state.  @xref{startup states}.
@end defvr

@defvr {Attr} string initdefault
Default runlevel.
@end defvr
@end deffn

@deffn {Request} PUT /runlevel/@{"runlevel":@var{L}@}
Initiates transition from the current runlevel to runlevel @var{L}
(@pxref{Runlevels}).
@end deffn

@node /environ
@appendixsec /environ
    This URI is active when @command{pies} runs as init process
(@pxref{Init Process}).  It manipulates the program initial
environment, i.e. the environment that all programs inherit.
@xref{Init Environment}.

@deffn {Request} GET /environ/
Returns entire environment formatted as a JSON array of strings.  On
success, the 200 response is returned:

@example
["RUNLEVEL=3", "CONSOLE=/dev/tty", ...]  
@end example
@end deffn

@deffn {Request} GET /environ/@var{var}
Returns the value of the environment variable @var{var}, if such is
defined.  On success, the 200 response carries the object:

@example
@{ "status":"OK", "value":@var{string} @}
@end example

@noindent
If the variable @var{var} is not defined, a 404 response is returned.
On error, a 403 response is returned.  In both cases, the response
body is the usual @command{pies} diagnostics object:

@example
@{ "status":"ER", "message":@var{text} @}
@end example
@end deffn

@deffn {Request} DELETE /environ/@var{var}
Deletes from the environment the variable @var{var}.  On success,
responds with HTTP 200:

@example
@{ "status":"OK" @}
@end example

Error responses are the same as for @samp{GET}.
@end deffn

@deffn {Request} PUT /environ/@var{name}=@var{value}
Initializes environment variable @var{name} to @var{value}.  See
@samp{GET} for the possible responses.
@end deffn



