(*
Module: Systemd
Parses systemd unit files.
Author: Dominic Cleal
About: Reference
This lens tries to keep as close as possible to systemd.unit(5) and
systemd.service(5) etc where possible.
About: License
This file is licenced under the LGPL v2+, like the rest of Augeas.
About: Lens Usage
To be documented
About: Configuration files
This lens applies to /lib/systemd/system/* and /etc/systemd/system/*.
See .
*)
module Systemd =
autoload xfm
(************************************************************************
* Group: USEFUL PRIMITIVES
*************************************************************************)
(* View: eol *)
let eol = Util.eol
(* View: comment
An entry *)
let comment = IniFile.comment IniFile.comment_re "#"
(* View: sep
An entry *)
let sep = IniFile.sep "=" "="
(* Variable: entry_single_kw *)
let entry_single_kw = "Description"
(* Variable: entry_command_kw *)
let entry_command_kw = /Exec[A-Za-z][A-Za-z0-9._-]+/
(* Variable: entry_env_kw *)
let entry_env_kw = "Environment"
(* Variable: entry_multi_kw *)
let entry_multi_kw = /[A-Za-z][A-Za-z0-9._-]+/
- entry_single_kw
- entry_command_kw
- entry_env_kw
(* Variable: value_single_re *)
let value_single_re = /[^;# \t\n\\][^;#\n\\]*[^;# \t\n\\]|[^;# \t\n\\]/
(* View: sto_value_single
Support multiline values with a backslash *)
let sto_value_single = Util.del_opt_ws ""
. store (value_single_re
. (/\\\\\n/ . value_single_re)*)
(* View: sto_value *)
let sto_value = store /[^;# \t\n\\]+/
(* Variable: value_sep
Multi-value entries separated by whitespace or backslash and newline *)
let value_sep = del /[ \t]+|[ \t]*\\\\[ \t]*\n[ \t]*/ " "
(* Variable: value_cmd_re
Don't parse @ and - prefix flags *)
let value_cmd_re = /[^;#@ \t\n\\-][^;#@ \t\n\\-][^;# \t\n\\]*/
(* Variable: env_key *)
let env_key = /[A-Za-z0-9_]+(\[[0-9]+\])?/
(************************************************************************
* Group: ENTRIES
*************************************************************************)
(*
Supported entry features, selected by key names:
* multi-value space separated attrs (the default)
* single-value attrs (Description)
* systemd.service: Exec* attrs with flags, command and arguments
* systemd.service: Environment NAME=arg
*)
(* View: entry_fn
Prototype for our various key=value lines, with optional comment *)
let entry_fn (kw:regexp) (val:lens) =
[ key kw . sep . val . (comment|eol) ]
(* View: entry_value
Store a value that doesn't contain spaces *)
let entry_value = [ label "value" . sto_value ]
(* View: entry_single
Entry that takes a single value containing spaces *)
let entry_single = entry_fn entry_single_kw
[ label "value" . sto_value_single ]?
(* View: entry_command
Entry that takes a space separated set of values (the default) *)
let entry_multi = entry_fn entry_multi_kw
( Util.del_opt_ws ""
. Build.opt_list entry_value value_sep )?
(* View: entry_command_flags
Exec* flags "@" and "-". Order is important, see systemd.service(8) *)
let entry_command_flags =
let exit = [ label "ignoreexit" . Util.del_str "-" ]
in let arg0 = [ label "arg0" . Util.del_str "@" ]
in exit? . arg0?
(* View: entry_command
Entry that takes a command, arguments and the optional prefix flags *)
let entry_command =
let cmd = [ label "command" . store value_cmd_re ]
in let arg = [ seq "args" . sto_value ]
in let args = [ counter "args" . label "arguments" . value_sep
. ( arg . value_sep )* . arg ]
in entry_fn entry_command_kw ( entry_command_flags . cmd . args? )?
(* View: entry_env
Entry that takes a space separated set of ENV=value key/value pairs *)
let entry_env =
let envkv = [ key env_key . Util.del_str "=" . ( sto_value )? ]
in entry_fn entry_env_kw ( Build.opt_list envkv value_sep )
(************************************************************************
* Group: LENS
*************************************************************************)
(* View: entry
An *)
let entry = entry_single | entry_multi | entry_command | entry_env | comment
(* View: include
Includes another file at this position *)
let include = [ key ".include" . Util.del_ws_spc . sto_value
. (comment|eol) ]
(* View: title
An *)
let title = IniFile.title IniFile.record_re
(* View: record
An *)
let record = IniFile.record title (entry|include)
(* View: lns
An *)
let lns = IniFile.lns record (comment|include)
(* View: filter *)
let filter = incl "/lib/systemd/system/*"
. incl "/lib/systemd/system/*/*"
. incl "/etc/systemd/system/*"
. incl "/etc/systemd/system/*/*"
. Util.stdexcl
let xfm = transform lns filter