[systemd-commits] 3 commits - Makefile.am man/tmpfiles.d.xml src/main.c src/systemctl-bash-completion.sh TODO

Lennart Poettering lennart at kemper.freedesktop.org
Wed Nov 10 14:18:44 PST 2010


 Makefile.am                      |    4 
 TODO                             |    2 
 man/tmpfiles.d.xml               |  169 ++++++++++++++++++++++-----------------
 src/main.c                       |   20 ++++
 src/systemctl-bash-completion.sh |  145 +++++++++++++++++++++++++++++++++
 5 files changed, 268 insertions(+), 72 deletions(-)

New commits:
commit 6ee5bbf85ce18cf07269a674d96f3a1d0ec7bf6b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 10 23:18:34 2010 +0100

    main: warn if /etc/mtab is not a symlink

diff --git a/TODO b/TODO
index a97ba9f..3264bbf 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,3 @@
-* print error if /etc/mtab is not a symlink to /proc/self/mounts
-
 * oneshot services which do not remain: 'exited' instead of 'dead'?
   it should be visible in 'systemctl' that they have been run
 
diff --git a/src/main.c b/src/main.c
index ea2f0c1..71e684b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -890,6 +890,24 @@ static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
         return t;
 }
 
+static void test_mtab(void) {
+        char *p;
+
+        if (readlink_malloc("/etc/mtab", &p) >= 0) {
+                bool b;
+
+                b = streq(p, "/proc/self/mounts");
+                free(p);
+
+                if (b)
+                        return;
+        }
+
+        log_error("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
+                  "This is not supported anymore. "
+                  "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
+}
+
 int main(int argc, char *argv[]) {
         Manager *m = NULL;
         int r, retval = EXIT_FAILURE;
@@ -1048,6 +1066,8 @@ int main(int argc, char *argv[]) {
                 loopback_setup();
 
                 mkdir_p("/dev/.systemd/ask-password/", 0755);
+
+                test_mtab();
         }
 
         if ((r = manager_new(arg_running_as, &m)) < 0) {

commit 42bb3074fe9632d7aa0fee825ad30d2083c3c629
Author: Ran Benita <ran234 at gmail.com>
Date:   Tue Nov 9 01:03:27 2010 +0200

    add bash completion for systemctl --system
    
    I've been playing recently with systemd on Arch, and had much fun. But
    soon, alas, my fingers started to ache from repeatedly writing
    systemctl restart some-long-service.service. So, I wrote a completion
    script. I figured other people may want to use it, so I prepared a
    patch against systemd-git (attached).
    
    There are some notes/disclaimers, however:
    
    - It requires bash>=4.0, sed, grep and awk. A bash-completion package
    is not strictly needed; sourcing the file is enough.
    - It wouldn't work properly with --session, as I had no way to test it.
    - It uses the output of systemctl list-units directly when that's
    enough, but also runs systemctl show when completing on some verbs
    (for example, to check for AllowIsolate=yes). This /may/ be somewhat
    slow once there are many units, since it calls a dbus method on each
    one. Is there a faster way to have that information?
    - The code is perhaps a bit long and messy; honestly, I blame the tool ;)
    
    One way to improve on the situation is to integrate some completion
    code in systemctl itself, the way e.g. gdbus, gsettings and django do
    it. This will allow for finer grained and faster completions, and it
    won't be necessary to keep the verb/option tables in sync with some
    other file. But it does mean adding all of this code in C. If this is
    acceptable, I'll try to have a go at it.
    
    Finally, a couple of completion tips I run into:
    - If you alias systemctl to, say, sctl, you get completions on that
    too by running to following command:
    complete -F _systemctl sctl
    - Add the following line to your .inputrc, to have the completion show
    after only a single tab press:
    set show-all-if-ambiguous on
    It makes the shell quite more pleasant.
    
    Hope it's good enough!
    
    Ran

diff --git a/Makefile.am b/Makefile.am
index 69faa55..f2d20c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,6 +26,7 @@ udevrulesdir=@udevrulesdir@
 pamlibdir=@pamlibdir@
 pkgconfigdatadir=$(datadir)/pkgconfig
 polkitpolicydir=$(datadir)/polkit-1/actions
+bashcompletiondir=${sysconfdir}/bash_completion.d
 
 # Our own, non-special dirs
 pkgsysconfdir=$(sysconfdir)/systemd
@@ -161,6 +162,9 @@ dbusinterface_DATA = \
 	org.freedesktop.systemd1.Swap.xml \
 	org.freedesktop.systemd1.Path.xml
 
+dist_bashcompletion_DATA = \
+        src/systemctl-bash-completion.sh
+
 dist_tmpfiles_DATA = \
 	tmpfiles.d/systemd.conf \
 	tmpfiles.d/x11.conf
diff --git a/src/systemctl-bash-completion.sh b/src/systemctl-bash-completion.sh
new file mode 100644
index 0000000..53f8e52
--- /dev/null
+++ b/src/systemctl-bash-completion.sh
@@ -0,0 +1,145 @@
+# This file is part of systemd.
+#
+# Copyright 2010 Ran Benita
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+__contains_word () {
+        local word=$1; shift
+        for w in $*; do [[ $w = $word ]] && return 0; done
+        return 1
+}
+
+__filter_units_by_property () {
+        local property=$1 value=$2 ; shift ; shift
+        local -a units=( $* )
+        local -a props=( $(systemctl show --property "$property" -- ${units[*]} | grep -v ^$) )
+        for ((i=0; $i < ${#units[*]}; i++)); do
+                if [[ "${props[i]}" = "$property=$value" ]]; then
+                        echo "${units[i]}"
+                fi
+        done
+}
+
+__get_all_units      () { systemctl list-units --full --all | awk '                 {print $1}' ; }
+__get_active_units   () { systemctl list-units --full       | awk '                 {print $1}' ; }
+__get_inactive_units () { systemctl list-units --full --all | awk '$3 == "inactive" {print $1}' ; }
+__get_failed_units   () { systemctl list-units --full       | awk '$3 == "failed"   {print $1}' ; }
+
+_systemctl () {
+        local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+        local verb comps
+
+        local -A OPTS=(
+               [STANDALONE]='--all -a --defaults --fail --force -f --full --global
+                             --help -h --no-ask-password --no-block --no-reload --no-wall
+                             --order --require --quiet -q --session --system --version'
+                      [ARG]='--kill-mode --kill-who --property -p --signal -s --type -t'
+        )
+
+        if __contains_word "$prev" ${OPTS[ARG]}; then
+                case $prev in
+                        --signal|-s)
+                                comps=$(compgen -A signal | grep '^SIG' | grep -Ev 'RTMIN|RTMAX|JUNK')
+                        ;;
+                        --type|-t)
+                                comps='automount device mount path service snapshot socket swap target timer'
+                        ;;
+                        --kill-who)
+                                comps='all control main'
+                        ;;
+                        --kill-mode)
+                                comps='control-group process process-group'
+                        ;;
+                        --property|-p)
+                                comps=''
+                        ;;
+                esac
+                COMPREPLY=( $(compgen -W "$comps" -- "$cur") )
+                return 0
+        fi
+
+
+        if [[ "$cur" = -* ]]; then
+                COMPREPLY=( $(compgen -W "${OPTS[*]}" -- "$cur") )
+                return 0
+        fi
+
+        local -A VERBS=(
+                [ALL_UNITS]='enable disable is-active is-enabled status show'
+             [FAILED_UNITS]='reset-failed'
+          [STARTABLE_UNITS]='start restart reload-or-restart'
+          [STOPPABLE_UNITS]='stop kill try-restart condrestart'
+         [ISOLATEBLE_UNITS]='isolate'
+         [RELOADABLE_UNITS]='reload reload-or-try-restart force-reload'
+                     [JOBS]='cancel'
+                [SNAPSHOTS]='delete'
+                     [ENVS]='set-environment unset-environment'
+               [STANDALONE]='daemon-reexec daemon-reload default dot dump emergency exit halt kexec
+                             list-jobs list-units poweroff reboot rescue show-environment'
+                     [NAME]='snapshot load'
+        )
+
+        local verb
+        for ((i=0; $i <= $COMP_CWORD; i++)); do
+                if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+                 ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG}]}; then
+                        verb=${COMP_WORDS[i]}
+                        break
+                fi
+        done
+
+        if   [[ -z $verb ]]; then
+                comps="${VERBS[*]}"
+
+        elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then
+                comps=$( __get_all_units )
+
+        elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then
+                comps=$( __filter_units_by_property CanStart yes \
+                      $( __get_inactive_units | grep -Ev '\.(device|snapshot)$' ))
+
+        elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then
+                comps=$( __filter_units_by_property CanStop yes \
+                      $( __get_active_units ) )
+
+        elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then
+                comps=$( __filter_units_by_property CanReload yes \
+                      $( __get_active_units ) )
+
+        elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then
+                comps=$( __filter_units_by_property AllowIsolate yes \
+                      $( __get_all_units ) )
+
+        elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then
+                comps=$( __get_failed_units )
+
+        elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[NAME]}; then
+                comps=''
+
+        elif __contains_word "$verb" ${VERBS[JOBS]}; then
+                comps=$( systemctl list-jobs | awk '{print $1}' )
+
+        elif __contains_word "$verb" ${VERBS[SNAPSHOTS]}; then
+                comps=$( systemctl list-units --type snapshot --full --all | awk '{print $1}' )
+
+        elif __contains_word "$verb" ${VERBS[ENVS]}; then
+                comps=$( systemctl show-environment | sed 's_\([^=]\+=\).*_\1_' )
+                compopt -o nospace
+        fi
+
+        COMPREPLY=( $(compgen -W "$comps" -- "$cur") )
+        return 0
+}
+complete -F _systemctl systemctl

commit aeee2322a66d63e3071b95969a6cbd8ce8dc1053
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 10 23:01:20 2010 +0100

    man: minor tmpfiles(5) updates and reindenting

diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 5ff53ef..9a74991 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -48,82 +48,112 @@
         <refsect1>
                 <title>Description</title>
 
-		<para><command>systemd</command> uses <filename>/etc/tmpfiles.d/</filename> to describe the creation, cleaning and removal of temporary files and directories
-which usually reside in <filename>/var/run</filename> or <filename>/tmp</filename>).
-Each configuration file is named in the style of
-<filename>/etc/tmpfiles.d/&lt;program&gt;.conf</filename></para>
-
+		<para><command>systemd</command> uses
+		<filename>/etc/tmpfiles.d/</filename> to describe the
+		creation, cleaning and removal of temporary files and
+		directories which usually reside in
+		<filename>/var/run</filename> or
+		<filename>/tmp</filename>).  Each configuration file
+		is named in the style of
+		<filename>/etc/tmpfiles.d/&lt;program&gt;.conf</filename></para>
         </refsect1>
 
         <refsect1>
 		<title>Configuration Format</title>
 
-		<para>The configuration format is one line per path containing
-action, mode, ownership and age fields:</para>
-
-	<programlisting>type path          mode uid  gid  age
-d    /var/run/user 0755 root root 10d
-</programlisting>
-
-	<refsect2>
-		<title>type</title>
-                <variablelist>
-                        <varlistentry>
-                                <term><varname>f</varname></term>
-                                <listitem><para>create a file</para></listitem>
-                        </varlistentry>
+		<para>The configuration format is one line per path
+		containing action, mode, ownership and age
+		fields:</para>
+
+                <programlisting>type path          mode uid  gid  age
+d    /var/run/user 0755 root root 10d</programlisting>
+
+                <refsect2>
+                        <title>mode</title>
+
+                        <para>The file access mode to use for this
+                        file or directory. If ommited or when set to -
+                        the default is used: 0755 for directories,
+                        0644 for files.</para>
+                </refsect2>
+
+                <refsect2>
+                        <title>uid, gid</title>
+
+                        <para>The user and group to use for this file
+                        or directory. This may either be a numeric
+                        user/group ID or a user or group name. If
+                        ommited or when set to - the default 0 is
+                        used.</para>
+                </refsect2>
+
+                <refsect2>
+                        <title>type</title>
+                        <variablelist>
+                                <varlistentry>
+                                        <term><varname>f</varname></term>
+                                        <listitem><para>create a file if it doesn't exist yet</para></listitem>
+                                </varlistentry>
+
+                                <varlistentry>
+                                        <term><varname>F</varname></term>
+                                        <listitem><para>create or truncate a file</para></listitem>
+                                </varlistentry>
+
+                                <varlistentry>
+                                        <term><varname>d</varname></term>
+                                        <listitem><para>create a directory if it doesn't exist yet</para></listitem>
+                                </varlistentry>
+
+                                <varlistentry>
+                                        <term><varname>D</varname></term>
+                                        <listitem><para>create or empty a directory</para></listitem>
+                                </varlistentry>
+
+                                <varlistentry>
+                                        <term><varname>x</varname></term>
+                                        <listitem><para>ignore a path</para></listitem>
+                                </varlistentry>
+
+                                <varlistentry>
+                                        <term><varname>r</varname></term>
+                                        <listitem><para>remove a path</para></listitem>
+                                </varlistentry>
+
+                                <varlistentry>
+                                        <term><varname>R</varname></term>
+                                        <listitem><para>recursively remove a path</para></listitem>
+                                </varlistentry>
+                        </variablelist>
+                </refsect2>
+
+                <refsect2>
+                        <title>age</title>
+                        <para>The date field, when set, is used to
+                        decide what files to delete when cleaning. If
+                        a file or directory is older than the current
+                        time minus the age field it is deleted. The
+                        field format is a series of integers each
+                        followed by one of the following
+                        postfixes for the respective time units:</para>
+
+                        <variablelist>
+                                <varlistentry>
+                                <term><varname>s</varname></term>
+                                <term><varname>min</varname></term>
+                                <term><varname>h</varname></term>
+                                <term><varname>d</varname></term>
+                                <term><varname>w</varname></term>
+                                <term><varname>ms</varname></term>
+                                <term><varname>m</varname></term>
+                                <term><varname>us</varname></term></varlistentry>
+                        </variablelist>
 
-                        <varlistentry>
-                                <term><varname>F</varname></term>
-                                <listitem><para>truncate a file</para></listitem>
-                        </varlistentry>
+                        <para>If multiple integers and units are specified the time values are summed up.</para>
 
-                        <varlistentry>
-                                <term><varname>d</varname></term>
-                                <listitem><para>create a directory</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><varname>D</varname></term>
-                                <listitem><para>truncate a directory</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><varname>x</varname></term>
-                                <listitem><para>ignore the path</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><varname>r</varname></term>
-                                <listitem><para>remove the path</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><varname>R</varname></term>
-                                <listitem><para>recursively remove the path</para></listitem>
-                        </varlistentry>
-                </variablelist>
-	</refsect2>
-
-	<refsect2>
-		<title>age</title>
-		<para>The date field, when set, is used to decide what files to delete when cleaning. If a file or directory is older than the current time minus the age field it is deleted. The field format is an integer followed by one of the following postfixes:</para>
-                <variablelist>
-		<varlistentry><term><varname>sec</varname></term>
-		<term><varname>s</varname></term>
-		<term><varname>min</varname></term>
-		<term><varname>hr</varname></term>
-		<term><varname>h</varname></term>
-		<term><varname>d</varname></term>
-		<term><varname>w</varname></term>
-		<term><varname>msec</varname></term>
-		<term><varname>ms</varname></term>
-		<term><varname>m</varname></term>
-		<term><varname>usec</varname></term>
-		<term><varname>us</varname></term></varlistentry>
-                </variablelist>
-	</refsect2>
+                        <para>The age field only applies to lines starting with d, D and x. If ommited or set to - no automatic clean-up is done.</para>
 
+                </refsect2>
 
         </refsect1>
 
@@ -134,8 +164,7 @@ d    /var/run/user 0755 root root 10d
                         <para><command>screen</command> needs two directories created at boot with specific modes and ownership.</para>
 
                         <programlisting>d /var/run/screens 1777 root root 10d
-d /var/run/uscreens 0755 root root 10d
-</programlisting>
+d /var/run/uscreens 0755 root root 10d12h</programlisting>
                 </example>
         </refsect1>
 



More information about the systemd-commits mailing list