chiark / gitweb /
systemctl: fold systemd-install into systemctl
authorLennart Poettering <lennart@poettering.net>
Fri, 23 Jul 2010 22:53:33 +0000 (00:53 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 23 Jul 2010 22:53:33 +0000 (00:53 +0200)
Makefile.am
man/daemon.xml
man/systemctl.xml
man/systemd-install.xml [deleted file]
man/systemd.unit.xml
man/systemd.xml
src/install.c [deleted file]
src/systemctl.c

index 0c3262e02ee5bd491f72b952a8a6d5cd6a067690..bebfd2f7370a9ef35be9218c02a1da9a04605edd 100644 (file)
@@ -58,7 +58,6 @@ rootbin_PROGRAMS = \
        systemd-notify
 
 bin_PROGRAMS = \
        systemd-notify
 
 bin_PROGRAMS = \
-       systemd-install \
        systemd-cgls
 
 if HAVE_GTK
        systemd-cgls
 
 if HAVE_GTK
@@ -325,7 +324,6 @@ MANPAGES = \
        man/systemd.1 \
        man/systemctl.1 \
        man/systemadm.1 \
        man/systemd.1 \
        man/systemctl.1 \
        man/systemadm.1 \
-       man/systemd-install.1 \
        man/systemd-cgls.1 \
        man/systemd-notify.1 \
        man/sd_notify.3 \
        man/systemd-cgls.1 \
        man/systemd-notify.1 \
        man/sd_notify.3 \
@@ -494,6 +492,8 @@ systemctl_SOURCES = \
        src/systemctl.c \
        src/utmp-wtmp.c \
        src/dbus-common.c \
        src/systemctl.c \
        src/utmp-wtmp.c \
        src/dbus-common.c \
+       src/path-lookup.c \
+       src/sd-daemon.c \
        src/cgroup-show.c \
        src/cgroup-util.c
 
        src/cgroup-show.c \
        src/cgroup-util.c
 
@@ -512,20 +512,6 @@ systemd_notify_SOURCES = \
 systemd_notify_LDADD = \
        libsystemd-basic.la
 
 systemd_notify_LDADD = \
        libsystemd-basic.la
 
-systemd_install_SOURCES = \
-       src/install.c \
-       src/path-lookup.c \
-       src/dbus-common.c \
-       src/sd-daemon.c
-
-systemd_install_LDADD = \
-       libsystemd-basic.la \
-       $(DBUS_LIBS)
-
-systemd_install_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 systemd_cgls_SOURCES = \
        src/cgls.c \
        src/cgroup-show.c \
 systemd_cgls_SOURCES = \
        src/cgls.c \
        src/cgroup-show.c \
index fb22e6c6165d88f4d950542fba0e7a37baf0d25a..30d39d7be11eeaa177cfc17d95f74783969eee2e 100644 (file)
                         the hardware of the respective kind is plugged
                         in or otherwise becomes available. In a
                         new-style init system it is possible to bind
                         the hardware of the respective kind is plugged
                         in or otherwise becomes available. In a
                         new-style init system it is possible to bind
-                        activation to hardware plug/unplug events. In systemd,
-                        kernel devices appearing in the sysfs/udev
-                        device tree can be exposed as units if they
-                        are tagged with the string
+                        activation to hardware plug/unplug events. In
+                        systemd, kernel devices appearing in the
+                        sysfs/udev device tree can be exposed as units
+                        if they are tagged with the string
                         "<literal>systemd</literal>". Like any other
                         kind of unit they may then pull in other units
                         when activated (i.e. Plugged in) and thus
                         "<literal>systemd</literal>". Like any other
                         kind of unit they may then pull in other units
                         when activated (i.e. Plugged in) and thus
                         <filename>bluetoothd.service</filename> via
                         controlling a
                         <filename>bluetooth.target.wants/</filename>
                         <filename>bluetoothd.service</filename> via
                         controlling a
                         <filename>bluetooth.target.wants/</filename>
-                        symlink uniformly with a tool like
-                        <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                        symlink uniformly with a command like
+                        <command>enable</command> of
+                        <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                         instead of manipulating the udev
                         ruleset.</para>
                 </refsect2>
                         instead of manipulating the udev
                         ruleset.</para>
                 </refsect2>
                         install their systemd unit files in the
                         directory returned by <command>pkg-config
                         systemd
                         install their systemd unit files in the
                         directory returned by <command>pkg-config
                         systemd
-                        --variable=systemdsystemunitdir</command>
-                        (for system services),
-                        resp. <command>pkg-config systemd
+                        --variable=systemdsystemunitdir</command> (for
+                        system services), resp. <command>pkg-config
+                        systemd
                         --variable=systemdsessionunitdir</command>
                         (for session services). This will make the
                         services available in the system on explicit
                         --variable=systemdsessionunitdir</command>
                         (for session services). This will make the
                         services available in the system on explicit
                         installation (e.g. <command>rpm -i</command>
                         by the administrator) symlinks should be
                         created in the systemd configuration
                         installation (e.g. <command>rpm -i</command>
                         by the administrator) symlinks should be
                         created in the systemd configuration
-                        directories via the
-                        <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                        directories via the <command>enable</command>
+                        command of the
+                        <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                         tool, to activate them automatically on
                         boot.</para>
 
                         tool, to activate them automatically on
                         boot.</para>
 
@@ -823,20 +825,32 @@ endif</programlisting>
                         package managers:</para>
 
                         <programlisting>%post
                         package managers:</para>
 
                         <programlisting>%post
-/usr/bin/systemd-install --realize enable foobar.service foobar.socket >/dev/null 2>&amp;1 || :
+if [ $1 -eq 1 ]; then
+        # Enable (but don't start) the units by default
+        /bin/systemctl enable foobar.service foobar.socket >/dev/null 2>&amp;1 || :
+fi
 
 %preun
 
 %preun
-if [ "$1" -eq 0 ]; then
-        /usr/bin/systemd-install --realize disable foobar.service foobar.socket >/dev/null 2>&amp;1 || :
+if [ $1 -eq 0 ]; then
+        # Disable and stop the units
+        /bin/systemctl disable foobar.service foobar.socket >/dev/null 2>&amp;1 || :
+        /bin/systemctl stop foobar.service foobar.socket >/dev/null 2>&amp;1 || :
+fi
+
+%postun
+if [ $1 -ge 1 ] ; then
+        # On upgrade, reload init system configuration if we changed unit files
+        /bin/systemctl daemon-reload >/dev/null 2>&amp;1 || :
+        # On upgrade, restart the daemon
+        /bin/systemctl try-restart foobar.service >/dev/null 2>&amp;1 || :
 fi</programlisting>
 
                         <para>Depending on whether your service should
                         or should not be started/stopped/restarted
                         during package installation, deinstallation or
 fi</programlisting>
 
                         <para>Depending on whether your service should
                         or should not be started/stopped/restarted
                         during package installation, deinstallation or
-                        upgrade, a different argument to
-                        <option>--realize=</option> may be
+                        upgrade, a different set of commands may be
                         specified. See
                         specified. See
-                        <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                        <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                         for details.</para>
 
                 </refsect2>
                         for details.</para>
 
                 </refsect2>
@@ -909,7 +923,6 @@ fi</programlisting>
                 <title>See Also</title>
                 <para>
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                 <title>See Also</title>
                 <para>
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
index 678bf0b2eeaffaa1b082392e614159867a1c744f..6e4b203d8877ba80f545c4b01c2edbb29f83d1d4 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="systemd-install">
+<refentry id="systemctl">
 
         <refentryinfo>
                 <title>systemctl</title>
 
         <refentryinfo>
                 <title>systemctl</title>
@@ -96,8 +96,9 @@
 
                                 <listitem><para>When showing
                                 unit/job/manager information, limit
 
                                 <listitem><para>When showing
                                 unit/job/manager information, limit
-                                display to certain property names. If
-                                not specified all set properties are
+                                display to certain properties as
+                                specified as argument. If not
+                                specified all set properties are
                                 shown. The argument should be a
                                 property name, such as
                                 <literal>MainPID</literal>. If
                                 shown. The argument should be a
                                 property name, such as
                                 <literal>MainPID</literal>. If
                                 <term><option>--fail</option></term>
 
                                 <listitem><para>If the requested
                                 <term><option>--fail</option></term>
 
                                 <listitem><para>If the requested
-                                operation conflicts with an existing
-                                unfinished operation, fail the
-                                command. If this is not specified the
-                                requested operation will replace the
-                                pending job if
-                                necessary.</para></listitem>
+                                operation conflicts with a pending
+                                unfinished job, fail the command. If
+                                this is not specified the requested
+                                operation will replace the pending job,
+                                if necessary.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--quiet</option></term>
+                                <term><option>-q</option></term>
+
+                                <listitem><para>Suppress output to
+                                STDOUT in
+                                <command>snapshot</command>,
+                                <command>check</command>,
+                                <command>enable</command> and
+                                <command>disable</command>.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--no-block</option></term>
+
+                               <listitem><para>Do not synchronously wait for
+                               the requested operation to finish. If this is
+                               not specified the job will be verified,
+                               enqueued and <command>systemctl</command> will
+                               wait until it is completed. By passing this
+                               argument it is only verified and
+                               enqueued.</para></listitem> </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--system</option></term>
+
+                                <listitem><para>Talk to the systemd
+                                system manager. (Default)</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--session</option></term>
+
+                                <listitem><para>Talk to the systemd
+                                session manager of the calling user.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>--system</option></term>
+                                <term><option>--no-wall</option></term>
 
 
-                                <listitem><para>Talk to the systemd
-                                system manager. (Default)</para></listitem>
+                                <listitem><para>Don't send wall
+                                message before
+                                halt, power-off, reboot.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>--session</option></term>
+                                <term><option>--global</option></term>
 
 
-                                <listitem><para>Talk to the systemd
-                                session manager of the calling user.</para></listitem>
+                                <listitem><para>When used with
+                                <command>enable</command> and
+                                <command>disable</command>, operate on the
+                                global session configuÅ•ation
+                                directory, thus enabling or disabling
+                                a unit file globally for all future
+                                sessions of all users.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>--no-block</option></term>
+                                <term><option>--no-reload</option></term>
 
 
-                               <listitem><para>Do not synchronously wait for
-                               the requested operation to finish. If this is
-                               not specified the job will be verified,
-                               enqueued and <command>systemctl</command> will
-                               wait until it is completed. By passing this
-                               argument it is only verified and
-                               enqueued.</para></listitem> </varlistentry>
+                                <listitem><para>When used with
+                                <command>enable</command> and
+                                <command>disable</command>, do not
+                                implicitly reload daemon configuration
+                                after executing the
+                                changes.</para></listitem>
+                        </varlistentry>
 
                         <varlistentry>
 
                         <varlistentry>
-                                <term><option>--quiet</option></term>
-                                <term><option>-q</option></term>
+                                <term><option>--force</option></term>
 
 
-                                <listitem><para>Suppress output to
-                                STDOUT for <command>snapshot</command>
-                                and
-                                <command>check</command>.</para></listitem>
+                                <listitem><para>When used with
+                                <command>enable</command>, override any
+                                existing conflicting
+                                symlinks.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>--no-wall</option></term>
+                                <term><option>--defaults</option></term>
 
 
-                                <listitem><para>Don't send wall
-                                message before
-                                halt, power-off, reboot.</para></listitem>
+                                <listitem><para>When used with
+                                <command>disable</command>, ensures
+                                that only the symlinks created by
+                                <command>enable</command> are removed,
+                                not all symlinks pointing to the unit
+                                file that shall be
+                                disabled.</para></listitem>
                         </varlistentry>
                 </variablelist>
 
                         </varlistentry>
                 </variablelist>
 
                         <varlistentry>
                                 <term><command>start [NAME...]</command></term>
 
                         <varlistentry>
                                 <term><command>start [NAME...]</command></term>
 
-                                <listitem><para>Start one or more
-                                units specified on the command
+                                <listitem><para>Start (activate) one
+                                or more units specified on the command
                                 line.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>stop [NAME...]</command></term>
 
                                 line.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>stop [NAME...]</command></term>
 
-                                <listitem><para>Stop one or more units
-                                specified on the command
+                                <listitem><para>Stop (deactivate) one
+                                or more units specified on the command
                                 line.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>reload [NAME...]</command></term>
 
                                 line.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>reload [NAME...]</command></term>
 
-                                <listitem><para>Asks all services
-                                whose units are listed on the command
-                                line to reload their
+                                <listitem><para>Asks all units listed
+                                on the command line to reload their
                                 configuration. Note that this will
                                 configuration. Note that this will
-                                reload the daemon configuration
-                                itself, not the unit configuration
-                                file of systemd. If you want systemd
-                                to reload the configuration file of a
-                                unit use the
+                                reload the service-specific
+                                configuration, not the unit
+                                configuration file of systemd. If you
+                                want systemd to reload the
+                                configuration file of a unit use the
                                 <command>daemon-reload</command>
                                 command. In other words: for the
                                 example case of Apache, this will
                                 <command>daemon-reload</command>
                                 command. In other words: for the
                                 example case of Apache, this will
                                 <filename>httpd.conf</filename> in the
                                 web server, not the
                                 <filename>apache.service</filename>
                                 <filename>httpd.conf</filename> in the
                                 web server, not the
                                 <filename>apache.service</filename>
-                                systemd unit file. </para> <para>This
-                                command should not be confused with
-                                the <command>daemon-reload</command>
-                                or <command>load</command>
+                                systemd unit file. </para>
+
+                                <para>This command should not be
+                                confused with the
+                                <command>daemon-reload</command> or
+                                <command>load</command>
                                 commands.</para></listitem>
 
                         </varlistentry>
                                 commands.</para></listitem>
 
                         </varlistentry>
                                 <term><command>reload-or-try-restart [NAME...]</command></term>
 
                                 <listitem><para>Reload one or more
                                 <term><command>reload-or-try-restart [NAME...]</command></term>
 
                                 <listitem><para>Reload one or more
-                                units if they support it. If not
-                                restart them
-                                instead.</para></listitem>
+                                units if they support it. If not,
+                                restart them instead. Note that for
+                                compatibility with SysV and Red Hat
+                                init scripts
+                                <command>force-reload</command> and
+                                <command>condrestart</command> may be
+                                used as equivalent commands to
+                                <command>reload-or-try-restart</command>.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>isolate [NAME]</command></term>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>isolate [NAME]</command></term>
                                 others.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 others.</para></listitem>
                         </varlistentry>
                         <varlistentry>
-                                <term><command>check [NAME...]</command></term>
+                                <term><command>is-active [NAME...]</command></term>
 
                                 <listitem><para>Check whether any of
                                 the specified units is active
 
                                 <listitem><para>Check whether any of
                                 the specified units is active
-                                (i.e. running). Returns 0 if at least
-                                one is active, non-zero
+                                (i.e. running). Returns an exit code
+                                0 if at least one is active, non-zero
                                 otherwise. Unless
                                 <option>--quiet</option> is specified
                                 this will also print the current unit
                                 otherwise. Unless
                                 <option>--quiet</option> is specified
                                 this will also print the current unit
                         <varlistentry>
                                 <term><command>status [NAME...]</command></term>
 
                         <varlistentry>
                                 <term><command>status [NAME...]</command></term>
 
-                                <listitem><para>Show short status
-                                information about one or more
-                                units. This shows terse runtime
-                                information about
-                                units.</para></listitem>
+                                <listitem><para>Show terse runtime
+                                status information about one or more
+                                units. This function is intended to
+                                generate human-readable output. If you
+                                are looking for computer-parsable
+                                output, use <command>show</command>
+                                instead.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>show [NAME...|JOB...]</command></term>
 
                         </varlistentry>
                         <varlistentry>
                                 <term><command>show [NAME...|JOB...]</command></term>
 
-                                <listitem><para>Show properties of
-                                one or more units, jobs or the manager
+                                <listitem><para>Show properties of one
+                                or more units, jobs or the manager
                                 itself. If no argument is specified
                                 properties of the manager will be
                                 shown. If a unit name is specified
                                 itself. If no argument is specified
                                 properties of the manager will be
                                 shown. If a unit name is specified
-                                properties of the unit is shown,
-                                and if a job id is specified
-                                properties of the job is
-                                shown.</para></listitem>
+                                properties of the unit is shown, and
+                                if a job id is specified properties of
+                                the job is shown. By default, empty
+                                properties are suppressed. Use
+                                <option>--all</option> to show those
+                                too. To select specific properties to
+                                show use
+                                <option>--property=</option>. This
+                                command is intended to be used
+                                whenever computer-parsable output is
+                                required. Use
+                                <command>status</command> if you are
+                                looking for formatted human-readable
+                                output.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
                                 command.</para></listitem>
                         </varlistentry>
 
                                 command.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><command>enable [NAME...]</command></term>
+
+                                <listitem><para>Enable one or more
+                                unit files, as specified on the
+                                command line. This will create a
+                                number of symlinks as encoded in the
+                                <literal>[Install]</literal> sections
+                                of the unit files. After the symlinks
+                                have been created the systemd
+                                configuration is reloaded (in a way
+                                that is equivalent to
+                                <command>daemon-reload</command>) to
+                                ensure the changes are taken into
+                                account immediately. Note that this
+                                does not have the effect that any of
+                                the units enabled are also started at
+                                the same time. If this is desired a
+                                seperate <command>start</command>
+                                command must be invoked for the
+                                unit.</para>
+
+                                <para>This command will
+                                print the actions executed. This
+                                output may be suppressed by passing
+                                <option>--quiet</option>.</para>
+
+                                <para>Note that this operation creates
+                                only the suggested symlinks for the
+                                units. While this command is the
+                                recommended way to manipulate the unit
+                                configuration directory, the
+                                administrator is free to make
+                                additional changes manually, by
+                                placing or removing symlinks in the
+                                directory. This is particular useful
+                                to create configurations that deviate
+                                from the suggested default
+                                installation. In this case the
+                                administrator must make sure to invoke
+                                <command>daemon-reload</command>
+                                manually as necessary, to ensure his
+                                changes are taken into account.</para>
+
+                                <para>Enabling units should not be
+                                confused with starting (activating)
+                                units, as done by the
+                                <command>start</command>
+                                command. Enabling and starting units
+                                is orthogonal: units may be enabled
+                                without being started and started
+                                without being enabled. Enabling simply
+                                hooks the unit into various suggested
+                                places (for example, so that the unit
+                                is automatically started on boot or
+                                when a particular kind of hardware is
+                                plugged in). Starting actually spawns
+                                the daemon process (in case of service
+                                units), or binds the socket (in case
+                                of socket units), and so
+                                on.</para>
+
+                                <para>Depending on whether
+                                <option>--system</option>,
+                                <option>--session</option> or
+                                <option>--global</option> is specified
+                                this enables the unit for the system,
+                                for sessions of the calling user only
+                                or for all future session of all
+                                users. Note that in the latter case no
+                                systemd daemon configuration is
+                                reloaded.</para>
+                                </listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>disable [NAME...]</command></term>
+
+                                <listitem><para>Disables one or more
+                                units. This removes all symlinks to
+                                the specified unit files from the unit
+                                configuration directory, and hence
+                                undoes the changes made by
+                                <command>enable</command>. Note
+                                however that this by default removes
+                                all symlinks to the unit files
+                                (i.e. including manual additions), not
+                                just those actually created by
+                                <command>enable</command>. If only the
+                                symlinks that are suggested by default
+                                shall be removed, pass
+                                <option>--defaults</option>. This
+                                implicitly reloads the systemd daemon
+                                configuration after completing the
+                                disabling of the units. Note that this
+                                command does not implicitly stop the
+                                units that is being disabled. If this
+                                is desired an additional
+                                <command>stop</command>command should
+                                be executed afterwards.</para>
+
+                                <para>This command will print the
+                                actions executed. This output may be
+                                suppressed by passing
+                                <option>--quiet</option>.</para>
+                                </listitem>
+
+                                <para>This command honours
+                                <option>--system</option>,
+                                <option>--session</option>,
+                                <option>--global</option> in a similar
+                                way as
+                                <command>enable</command>.</para>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>is-enabled [NAME...]</command></term>
+
+                                <listitem><para>Checks whether any of
+                                the specified unit files is enabled
+                                (as with
+                                <command>enable</command>). Returns an
+                                exit code of 0 if at least one is
+                                enabled, non-zero
+                                otherwise.</para></listitem>
+                        </varlistentry>
+
                         <varlistentry>
                                 <term><command>load [NAME...]</command></term>
 
                         <varlistentry>
                                 <term><command>load [NAME...]</command></term>
 
                                 <listitem><para>Cancel one or more
                                 jobs specified on the command line by
                                 their numeric job
                                 <listitem><para>Cancel one or more
                                 jobs specified on the command line by
                                 their numeric job
-                                IDs.</para></listitem>
-                        </varlistentry>
-                        <varlistentry>
-                                <term><command>clear-jobs</command></term>
-
-                                <listitem><para>Cancel all jobs that are in progress.</para></listitem>
+                                IDs. If not job id is specified cancels all jobs that are pending.</para></listitem>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>monitor</command></term>
                         </varlistentry>
                         <varlistentry>
                                 <term><command>monitor</command></term>
diff --git a/man/systemd-install.xml b/man/systemd-install.xml
deleted file mode 100644 (file)
index 228a916..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<!--
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  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/>.
--->
-
-<refentry id="systemd-install">
-
-        <refentryinfo>
-                <title>systemd-install</title>
-                <productname>systemd</productname>
-
-                <authorgroup>
-                        <author>
-                                <contrib>Developer</contrib>
-                                <firstname>Lennart</firstname>
-                                <surname>Poettering</surname>
-                                <email>lennart@poettering.net</email>
-                        </author>
-                </authorgroup>
-        </refentryinfo>
-
-        <refmeta>
-                <refentrytitle>systemd-install</refentrytitle>
-                <manvolnum>1</manvolnum>
-        </refmeta>
-
-        <refnamediv>
-                <refname>systemd-install</refname>
-                <refpurpose>Enable or disable a systemd unit
-                definition file</refpurpose>
-        </refnamediv>
-
-        <refsynopsisdiv>
-                <cmdsynopsis>
-                        <command>systemd-install <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="plain">enable</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
-                </cmdsynopsis>
-                <cmdsynopsis>
-                        <command>systemd-install <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="plain">disable</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
-                </cmdsynopsis>
-                <cmdsynopsis>
-                        <command>systemd-install <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="plain">realize</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
-                </cmdsynopsis>
-                <cmdsynopsis>
-                        <command>systemd-install <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="plain">test</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
-                </cmdsynopsis>
-        </refsynopsisdiv>
-
-        <refsect1>
-                <title>Description</title>
-
-                <para><command>systemd-install</command> enables or
-                disables systemd units, or checks whether they are
-                enabled, according to the installation suggestions
-                included in the unit files.</para>
-
-                <para>This command is useful to apply or undo the
-                installation instructions encoded in the <literal>[Install]</literal>
-                section of unit files. See
-                <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-                for more information.</para>
-
-                <para>Enabling units (as with <command>systemd-install
-                enable</command>) should not be confused with
-                activating units (as with <command>systemctl
-                start</command>). The former simply installs the unit
-                files in the configuration tree, but does not start
-                them. The latter equals starting them, but does not
-                necessarily require them to be enabled.</para>
-
-                <para>Note that while
-                <command>systemd-install</command> is the recommended
-                tool to create or remove symlinks in the systemd
-                configuration directory the administrator can also
-                create links there manually, which is particularly
-                useful to use configurations that deviate from the
-                installation suggestions included in the unit
-                files.</para>
-        </refsect1>
-
-        <refsect1>
-                <title>Options</title>
-
-                <para>The following options are understood:</para>
-
-                <variablelist>
-                        <varlistentry>
-                                <term><option>--help</option></term>
-
-                                <listitem><para>Prints a short help
-                                text and exits.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--force</option></term>
-
-                                <listitem><para>Enable/disable a
-                                service even if it conflicts
-                                with/contradicts another service. This
-                                might have the effect of disabling
-                                another service that was
-                                enabled.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--system</option></term>
-
-                                <listitem><para>Enable/disable a
-                                system service.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--session</option></term>
-
-                                <listitem><para>Enable/disable a
-                                session service for the calling
-                                user.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--global</option></term>
-
-                                <listitem><para>Enable/disable a
-                                session service for all
-                                users.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--realize[=MODE]</option></term>
-
-                                <listitem><para>After
-                                enabling/disabling stop/restart/stop
-                                the unit and reload manager
-                                configuration. Optionally, takes one
-                                of <option>no</option>,
-                                <option>reload</option>,
-                                <option>minimal</option>,
-                                <option>maybe</option> or
-                                <option>yes</option>. If
-                                <option>no</option> is passed the
-                                manager will not reload its
-                                configuration and no service will be
-                                started or stopped after
-                                enabling/disabling of the unit
-                                files. If <option>reload</option> is
-                                passed the daemon configuration is
-                                reloaded but the unit otherwise not
-                                started/stopped/restarted. If
-                                <option>minimal</option> is passed and
-                                a unit is being enabled it will also
-                                be restarted should it already be
-                                running. If a unit is being disabled
-                                it will be stopped should it be
-                                running. In either case the daemon
-                                configuration is
-                                reloaded. <option>maybe</option> is
-                                similar to this, but the unit will
-                                also be started if it is being enabled
-                                and any of the units listed in
-                                <varname>WantedBy=</varname> in the
-                                <literal>[Install]</literal> section
-                                of the unit file is already
-                                activated. Finally
-                                <option>yes</option> starts the unit
-                                unconditionally after enabling. This
-                                setting defaults to
-                                <option>no</option>. If
-                                <option>--realize</option> is
-                                specifieed but the mode value is
-                                omitted defaults to
-                                <option>minimal</option>. This option
-                                has no effect when
-                                <option>--global</option> or
-                                <command>test</command> is used, or
-                                when systemd is not running or the
-                                command is executed in a
-                                <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-                                environment. This option is implied if
-                                the <command>realize</command> command
-                                is used.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--all</option></term>
-
-                                <listitem><para>If set makes sure that
-                                all symlinks on the specified unit are
-                                removed from the configuration
-                                directory and its subdirectories, not
-                                just those specified in the
-                                <literal>[Install]</literal>
-                                section.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><option>--verbose</option></term>
-                                <term><option>-v</option></term>
-
-                                <listitem><para>Show what is done as
-                                it is done.</para></listitem>
-                        </varlistentry>
-
-                </variablelist>
-
-                <para>The following commands are understood:</para>
-
-                <variablelist>
-                        <varlistentry>
-                                <term><command>enable</command></term>
-
-                                <listitem><para>Enable one or more
-                                units. This will create a number of
-                                symlinks as encoded in the
-                                <literal>[Install]</literal> section
-                                of a unit file.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><command>disable</command></term>
-
-                                <listitem><para>Disable or more
-                                units. This will remove a number of
-                                symlinks as encoded in the
-                                <literal>[Install]</literal> section
-                                of a unit file.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><command>realize</command></term>
-
-                                <listitem><para>Does not enable or
-                                disable any unit. Checks whether any
-                                of the units specified are enabled,
-                                and then starts/stops/restarts the
-                                units accordingly. This will check for
-                                the existence of a number of symlinks
-                                as encoded in the
-                                <literal>[Install]</literal> section
-                                of a unit file, and then executes the
-                                action normally specified by
-                                <option>--realize</option>. If
-                                <option>--realize</option> is not
-                                specified implies
-                                <option>minimal</option> mode. To
-                                override this mode specify
-                                <option>--realize=</option> in
-                                addition to
-                                <command>realize</command>.</para></listitem>
-                        </varlistentry>
-
-                        <varlistentry>
-                                <term><command>test</command></term>
-
-                                <listitem><para>Does not enable or
-                                disable any unit. Checks whether any
-                                of the units specified are
-                                enabled. This will check for the
-                                existence of a number of symlinks as
-                                encoded in the
-                                <literal>[Install]</literal> section
-                                of a unit file, and return with an
-                                exit code of 0 if a unit is enabled, 1
-                                otherwise.</para></listitem>
-                        </varlistentry>
-
-                </variablelist>
-
-        </refsect1>
-
-        <refsect1>
-                <title>Exit status</title>
-
-                <para>On success 0 is returned, a non-zero failure
-                code otherwise.</para>
-        </refsect1>
-
-        <refsect1>
-                <title>See Also</title>
-                <para>
-                        <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-                </para>
-        </refsect1>
-
-</refentry>
index 7284524dbbae65b58567efd4da29cf0b1a0de5b0..585145ab375f333fe7384b6373ec2d43c25c4105 100644 (file)
                 <varname>Wanted=</varname> see below. The preferred
                 way to create symlinks in the
                 <filename>.wants/</filename> directory of a service is
                 <varname>Wanted=</varname> see below. The preferred
                 way to create symlinks in the
                 <filename>.wants/</filename> directory of a service is
-                with the
-                <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                with the <command>enable</command> command of the
+                <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                 tool which reads information from the [Install]
                 section of unit files. (See below.)</para>
 
                 tool which reads information from the [Install]
                 section of unit files. (See below.)</para>
 
                 section is not interpreted by
                 <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                 during runtime. It is used exclusively by the
                 section is not interpreted by
                 <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                 during runtime. It is used exclusively by the
-                <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                <command>enable</command> and
+                <command>disable</command> commands of the
+                <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                 tool during installation of a unit:</para>
 
                 <variablelist>
                 tool during installation of a unit:</para>
 
                 <variablelist>
                                 more than once, in which case all
                                 listed names are used. At installation
                                 time,
                                 more than once, in which case all
                                 listed names are used. At installation
                                 time,
-                                <command>systemd-install</command>
+                                <command>systemctl enable</command>
                                 will create symlinks from these names
                                 to the unit file name. Note that this
                                 is different from the
                                 will create symlinks from these names
                                 to the unit file name. Note that this
                                 is different from the
                                 <varname>Alias=</varname> apply only
                                 if the unit has actually been
                                 installed with the
                                 <varname>Alias=</varname> apply only
                                 if the unit has actually been
                                 installed with the
-                                <command>systemd-install</command>
-                                tool.  Also, if systemd searches for a
+                                <command>systemctl enable</command>
+                                command.  Also, if systemd searches for a
                                 unit, it will discover symlinked alias
                                 names as configured with
                                 <varname>Alias=</varname>, but not
                                 unit, it will discover symlinked alias
                                 names as configured with
                                 <varname>Alias=</varname>, but not
                                 installed. If the user requests
                                 installation of a unit with this
                                 option configured,
                                 installed. If the user requests
                                 installation of a unit with this
                                 option configured,
-                                <command>systemd-install</command>
+                                <command>systemctl enable</command>
                                 will automatically install units
                                 listed in this option as
                                 well.</para></listitem>
                                 will automatically install units
                                 listed in this option as
                                 well.</para></listitem>
                 <para>
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                 <para>
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
index c027b4f6600fb46d1011a3c29cd18ff12b625988..d2112b1bf02963d7d7f725f56e3fb56ff302816d 100644 (file)
                                 --variable=systemdsystemconfdir</command>
                                 returns the path of the system
                                 configuration directory. Packages
                                 --variable=systemdsystemconfdir</command>
                                 returns the path of the system
                                 configuration directory. Packages
-                                should alter the content of these directories
-                                only with the
-                                <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                                should alter the content of these
+                                directories only with the
+                                <command>enable</command> and
+                                <command>disable</command> commands of
+                                the
+                                <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                                 tool.</para></listitem>
                         </varlistentry>
                 </variablelist>
                                 tool.</para></listitem>
                         </varlistentry>
                 </variablelist>
                                 unit files in the directory returned
                                 by <command>pkg-config systemd
                                 --variable=systemdsessionunitdir</command>. Global
                                 unit files in the directory returned
                                 by <command>pkg-config systemd
                                 --variable=systemdsessionunitdir</command>. Global
-                                configuration is done in the
-                                directory reported by
-                                <command>pkg-config systemd
+                                configuration is done in the directory
+                                reported by <command>pkg-config
+                                systemd
                                 --variable=systemdsessionconfdir</command>. The
                                 --variable=systemdsessionconfdir</command>. The
-                                <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                                <command>enable</command> and
+                                <command>disable</command> commands of
+                                the
+                                <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                                 tool can handle both global (i.e. for
                                 all users) and private (for one user)
                                 enabling/disabling of
                                 tool can handle both global (i.e. for
                                 all users) and private (for one user)
                                 enabling/disabling of
                 <para>
                         <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemadm</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                 <para>
                         <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemadm</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd-notify</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd-notify</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
diff --git a/src/install.c b/src/install.c
deleted file mode 100644 (file)
index 2d6316a..0000000
+++ /dev/null
@@ -1,1165 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8 -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  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/>.
-***/
-
-#include <sys/stat.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-#include "log.h"
-#include "path-lookup.h"
-#include "util.h"
-#include "macro.h"
-#include "strv.h"
-#include "conf-parser.h"
-#include "dbus-common.h"
-#include "sd-daemon.h"
-
-static bool arg_force = false;
-static bool arg_all = false;
-static bool arg_verbose = false;
-
-static enum {
-        WHERE_SYSTEM,
-        WHERE_SESSION,
-        WHERE_GLOBAL,
-} arg_where = WHERE_SYSTEM;
-
-static enum {
-        ACTION_INVALID,
-        ACTION_ENABLE,
-        ACTION_DISABLE,
-        ACTION_REALIZE,
-        ACTION_TEST
-} arg_action = ACTION_INVALID;
-
-static enum {
-        REALIZE_NO,        /* Don't reload/start/stop or anything */
-        REALIZE_RELOAD,    /* Only reload daemon config, don't stop/start */
-        REALIZE_MINIMAL,   /* Only shutdown/restart if running. */
-        REALIZE_MAYBE,     /* Start if WantedBy= suggests */
-        REALIZE_YES        /* Start unconditionally */
-} arg_realize = REALIZE_NO;
-
-typedef struct {
-        char *name;
-        char *path;
-
-        char **aliases;
-        char **wanted_by;
-} InstallInfo;
-
-static Hashmap *will_install = NULL, *have_installed = NULL;
-static Set *remove_symlinks_to = NULL;
-
-static int help(void) {
-
-        printf("%s [OPTIONS...] {COMMAND} ...\n\n"
-               "Install init system units.\n\n"
-               "  -h --help           Show this help\n"
-               "     --force          Override existing links\n"
-               "     --verbose        Show what is being done as it is done\n"
-               "     --system         Install into system\n"
-               "     --session        Install into session\n"
-               "     --global         Install into all sessions\n"
-               "     --all            When disabling, remove all symlinks, not\n"
-               "                      just those listed in the [Install] section\n"
-               "     --realize[=MODE] Start/stop/restart unit after installation\n"
-               "                      Takes 'no', 'minimal', 'maybe' or 'yes'\n\n"
-               "Commands:\n"
-               "  enable [NAME...]    Enable one or more units\n"
-               "  disable [NAME...]   Disable one or more units\n"
-               "  realize [NAME...]   Test whether any of the specified units are enabled\n"
-               "                      and the start/stop/restart units accordingly\n"
-               "  test [NAME...]      Test whether any of the specified units are enabled\n",
-               program_invocation_short_name);
-
-        return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
-        enum {
-                ARG_SESSION = 0x100,
-                ARG_SYSTEM,
-                ARG_GLOBAL,
-                ARG_FORCE,
-                ARG_REALIZE,
-                ARG_ALL
-        };
-
-        static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'         },
-                { "session",   no_argument,       NULL, ARG_SESSION },
-                { "system",    no_argument,       NULL, ARG_SYSTEM  },
-                { "global",    no_argument,       NULL, ARG_GLOBAL  },
-                { "force",     no_argument,       NULL, ARG_FORCE   },
-                { "realize",   optional_argument, NULL, ARG_REALIZE },
-                { "all",       no_argument,       NULL, ARG_ALL     },
-                { "verbose",   no_argument,       NULL, 'v'         },
-                { NULL,        0,                 NULL, 0           }
-        };
-
-        int c;
-        bool realize_switch = false;
-
-        assert(argc >= 1);
-        assert(argv);
-
-        while ((c = getopt_long(argc, argv, "hv", options, NULL)) >= 0) {
-
-                switch (c) {
-
-                case 'h':
-                        help();
-                        return 0;
-
-                case ARG_SESSION:
-                        arg_where = WHERE_SESSION;
-                        break;
-
-                case ARG_SYSTEM:
-                        arg_where = WHERE_SYSTEM;
-                        break;
-
-                case ARG_GLOBAL:
-                        arg_where = WHERE_GLOBAL;
-                        break;
-
-                case ARG_FORCE:
-                        arg_force = true;
-                        break;
-
-                case ARG_REALIZE:
-
-                        realize_switch = true;
-
-                        if (!optarg)
-                                arg_realize = REALIZE_MINIMAL;
-                        else if (streq(optarg, "no"))
-                                arg_realize = REALIZE_NO;
-                        else if (streq(optarg, "minimal"))
-                                arg_realize = REALIZE_MINIMAL;
-                        else if (streq(optarg, "maybe"))
-                                arg_realize = REALIZE_MAYBE;
-                        else if (streq(optarg, "yes"))
-                                arg_realize = REALIZE_YES;
-                        else if (streq(optarg, "reload"))
-                                arg_realize = REALIZE_RELOAD;
-                        else {
-                                log_error("Invalid --realize argument %s", optarg);
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case ARG_ALL:
-                        arg_all = true;
-                        break;
-
-                case 'v':
-                        arg_verbose = true;
-                        break;
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        log_error("Unknown option code %c", c);
-                        return -EINVAL;
-                }
-        }
-
-        if (optind >= argc) {
-                help();
-                return -EINVAL;
-        }
-
-        if (streq(argv[optind], "enable"))
-                arg_action = ACTION_ENABLE;
-        else if (streq(argv[optind], "disable"))
-                arg_action = ACTION_DISABLE;
-        else if (streq(argv[optind], "test"))
-                arg_action = ACTION_TEST;
-        else if (streq(argv[optind], "realize")) {
-                arg_action = ACTION_REALIZE;
-
-                if (!realize_switch)
-                        arg_realize = REALIZE_MINIMAL;
-        } else {
-                log_error("Unknown verb %s.", argv[optind]);
-                return -EINVAL;
-        }
-
-        optind++;
-
-        if (optind >= argc) {
-                log_error("Missing unit name.");
-                return -EINVAL;
-        }
-
-
-        return 1;
-}
-
-static void install_info_free(InstallInfo *i) {
-        assert(i);
-
-        free(i->name);
-        free(i->path);
-        strv_free(i->aliases);
-        strv_free(i->wanted_by);
-        free(i);
-}
-
-static void install_info_hashmap_free(Hashmap *m) {
-        InstallInfo *i;
-
-        while ((i = hashmap_steal_first(m)))
-                install_info_free(i);
-
-        hashmap_free(m);
-}
-
-static bool unit_name_valid(const char *name) {
-
-        /* This is a minimal version of unit_name_valid() from
-         * unit-name.c */
-
-        if (!*name)
-                return false;
-
-        if (ignore_file(name))
-                return false;
-
-        return true;
-}
-
-static int install_info_add(const char *name) {
-        InstallInfo *i;
-        int r;
-
-        if (!unit_name_valid(name))
-                return -EINVAL;
-
-        if (hashmap_get(have_installed, name) ||
-            hashmap_get(will_install, name))
-                return 0;
-
-        if (!(i = new0(InstallInfo, 1))) {
-                r = -ENOMEM;
-                goto fail;
-        }
-
-        if (!(i->name = strdup(name))) {
-                r = -ENOMEM;
-                goto fail;
-        }
-
-        if ((r = hashmap_put(will_install, i->name, i)) < 0)
-                goto fail;
-
-        return 0;
-
-fail:
-        if (i)
-                install_info_free(i);
-
-        return r;
-}
-
-static int daemon_reload(DBusConnection *bus) {
-        DBusMessage *m = NULL, *reply = NULL;
-        DBusError error;
-        int r;
-
-        assert(bus);
-
-        dbus_error_init(&error);
-
-        if (arg_verbose)
-                log_info("Reloading daemon configuration.");
-
-        if (!(m = dbus_message_new_method_call(
-                              "org.freedesktop.systemd1",
-                              "/org/freedesktop/systemd1",
-                              "org.freedesktop.systemd1.Manager",
-                              "Reload"))) {
-                log_error("Could not allocate message.");
-                return -ENOMEM;
-        }
-
-        if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to reload configuration: %s", error.message);
-                r = -EIO;
-                goto finish;
-        }
-
-        r = 0;
-
-finish:
-        if (m)
-                dbus_message_unref(m);
-
-        if (reply)
-                dbus_message_unref(reply);
-
-        dbus_error_free(&error);
-
-        return r;
-}
-
-static int install_info_run(DBusConnection *bus, InstallInfo *i, bool enabled) {
-        DBusMessage *m = NULL, *reply = NULL;
-        DBusError error;
-        int r;
-        const char *mode = "replace";
-
-        assert(bus);
-        assert(i);
-
-        dbus_error_init(&error);
-
-        if (arg_action == ACTION_ENABLE ||
-            (arg_action == ACTION_REALIZE && enabled)) {
-
-                if (arg_realize == REALIZE_MAYBE) {
-                        char **k;
-                        bool yes_please = false;
-
-                        STRV_FOREACH(k, i->wanted_by) {
-                                DBusMessageIter sub, iter;
-
-                                const char *path, *state;
-                                const char *interface = "org.freedesktop.systemd1.Unit";
-                                const char *property = "ActiveState";
-
-                                if (!(m = dbus_message_new_method_call(
-                                                      "org.freedesktop.systemd1",
-                                                      "/org/freedesktop/systemd1",
-                                                      "org.freedesktop.systemd1.Manager",
-                                                      "GetUnit"))) {
-                                        log_error("Could not allocate message.");
-                                        r = -ENOMEM;
-                                        goto finish;
-                                }
-
-                                if (!dbus_message_append_args(m,
-                                                              DBUS_TYPE_STRING, k,
-                                                              DBUS_TYPE_INVALID)) {
-                                        log_error("Could not append arguments to message.");
-                                        r = -ENOMEM;
-                                        goto finish;
-                                }
-
-                                if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                                        /* Hmm, this unit doesn't exist, let's try the next one */
-                                        dbus_message_unref(m);
-                                        m = NULL;
-                                        continue;
-                                }
-
-                                if (!dbus_message_get_args(reply, &error,
-                                                           DBUS_TYPE_OBJECT_PATH, &path,
-                                                           DBUS_TYPE_INVALID)) {
-                                        log_error("Failed to parse reply: %s", error.message);
-                                        r = -EIO;
-                                        goto finish;
-                                }
-
-                                dbus_message_unref(m);
-                                if (!(m = dbus_message_new_method_call(
-                                                      "org.freedesktop.systemd1",
-                                                      path,
-                                                      "org.freedesktop.DBus.Properties",
-                                                      "Get"))) {
-                                        log_error("Could not allocate message.");
-                                        r = -ENOMEM;
-                                        goto finish;
-                                }
-
-                                if (!dbus_message_append_args(m,
-                                                              DBUS_TYPE_STRING, &interface,
-                                                              DBUS_TYPE_STRING, &property,
-                                                              DBUS_TYPE_INVALID)) {
-                                        log_error("Could not append arguments to message.");
-                                        r = -ENOMEM;
-                                        goto finish;
-                                }
-
-                                dbus_message_unref(reply);
-                                if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                                        log_error("Failed to issue method call: %s", error.message);
-                                        r = -EIO;
-                                        goto finish;
-                                }
-
-                                if (!dbus_message_iter_init(reply, &iter) ||
-                                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)  {
-                                        log_error("Failed to parse reply.");
-                                        r = -EIO;
-                                        goto finish;
-                                }
-
-                                dbus_message_iter_recurse(&iter, &sub);
-
-                                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)  {
-                                        log_error("Failed to parse reply.");
-                                        r = -EIO;
-                                        goto finish;
-                                }
-
-                                dbus_message_iter_get_basic(&sub, &state);
-
-                                dbus_message_unref(m);
-                                dbus_message_unref(reply);
-                                m = reply = NULL;
-
-                                if (streq(state, "active") ||
-                                    startswith(state, "reloading") ||
-                                    startswith(state, "activating")) {
-                                        yes_please = true;
-                                        break;
-                                }
-                        }
-
-                        if (!yes_please) {
-                                r = 0;
-                                goto finish;
-                        }
-                }
-
-                if (arg_verbose)
-                        log_info("Restarting %s.", i->name);
-
-                if (!(m = dbus_message_new_method_call(
-                                      "org.freedesktop.systemd1",
-                                      "/org/freedesktop/systemd1",
-                                      "org.freedesktop.systemd1.Manager",
-                                      arg_realize == REALIZE_MINIMAL ? "TryRestartUnit" : "RestartUnit"))) {
-                        log_error("Could not allocate message.");
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                if (!dbus_message_append_args(m,
-                                              DBUS_TYPE_STRING, &i->name,
-                                              DBUS_TYPE_STRING, &mode,
-                                              DBUS_TYPE_INVALID)) {
-                        log_error("Could not append arguments to message.");
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-
-        } else if (arg_action == ACTION_DISABLE ||
-                   (arg_action == ACTION_REALIZE && !enabled)) {
-
-                if (arg_verbose)
-                        log_info("Stopping %s.", i->name);
-
-                if (!(m = dbus_message_new_method_call(
-                                      "org.freedesktop.systemd1",
-                                      "/org/freedesktop/systemd1",
-                                      "org.freedesktop.systemd1.Manager",
-                                      "StopUnit"))) {
-                        log_error("Could not allocate message.");
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                if (!dbus_message_append_args(m,
-                                              DBUS_TYPE_STRING, &i->name,
-                                              DBUS_TYPE_STRING, &mode,
-                                              DBUS_TYPE_INVALID)) {
-                        log_error("Could not append arguments to message.");
-                        r = -ENOMEM;
-                        goto finish;
-                }
-        } else
-                assert_not_reached("install_info_run() called but nothing to do?");
-
-        if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to realize unit: %s", error.message);
-                r = -EIO;
-                goto finish;
-        }
-
-        r = 0;
-
-finish:
-        if (m)
-                dbus_message_unref(m);
-
-        if (reply)
-                dbus_message_unref(reply);
-
-        dbus_error_free(&error);
-
-        return r;
-}
-
-static int config_parse_also(
-                const char *filename,
-                unsigned line,
-                const char *section,
-                const char *lvalue,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        char *w;
-        size_t l;
-        char *state;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-
-        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
-                char *n;
-                int r;
-
-                if (!(n = strndup(w, l)))
-                        return -ENOMEM;
-
-                r = install_info_add(n);
-                free(n);
-
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-static int mark_symlink_for_removal(const char *p) {
-        char *n;
-        int r;
-
-        assert(p);
-        assert(path_is_absolute(p));
-
-        if (!remove_symlinks_to)
-                return 0;
-
-        if (!(n = canonicalize_file_name(p)))
-                if (!(n = strdup(p)))
-                        return -ENOMEM;
-
-        path_kill_slashes(n);
-
-        if ((r = set_put(remove_symlinks_to, n)) < 0) {
-                free(n);
-                return r;
-        }
-
-        return 0;
-}
-
-static int remove_marked_symlinks_fd(int fd, const char *config_path, const char *root, bool *deleted) {
-        int r = 0;
-        DIR *d;
-        struct dirent *de;
-
-        assert(fd >= 0);
-        assert(root);
-        assert(deleted);
-
-        if (!(d = fdopendir(fd)))
-                return -errno;
-
-        rewinddir(d);
-
-        while ((de = readdir(d))) {
-                bool is_dir = false, is_link = false;
-
-                if (ignore_file(de->d_name))
-                        continue;
-
-                if (de->d_type == DT_LNK)
-                        is_link = true;
-                else if (de->d_type == DT_DIR)
-                        is_dir = true;
-                else if (de->d_type == DT_UNKNOWN) {
-                        struct stat st;
-
-                        if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
-                                log_error("Failed to stat %s/%s: %m", root, de->d_name);
-
-                                if (r == 0)
-                                        r = -errno;
-                                continue;
-                        }
-
-                        is_link = S_ISLNK(st.st_mode);
-                        is_dir = S_ISDIR(st.st_mode);
-                } else
-                        continue;
-
-                if (is_dir) {
-                        int nfd, q;
-                        char *p;
-
-                        if ((nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW)) < 0) {
-                                log_error("Failed to open %s/%s: %m", root, de->d_name);
-
-                                if (r == 0)
-                                        r = -errno;
-                                continue;
-                        }
-
-                        if (asprintf(&p, "%s/%s", root, de->d_name) < 0) {
-                                log_error("Failed to allocate directory string.");
-                                close_nointr_nofail(nfd);
-                                r = -ENOMEM;
-                                break;
-                        }
-
-                        q = remove_marked_symlinks_fd(nfd, config_path, p, deleted);
-                        free(p);
-                        close_nointr_nofail(nfd);
-
-                        if (r == 0)
-                                q = r;
-
-                } else if (is_link) {
-                        char *p, *dest, *c;
-                        int q;
-
-                        if (asprintf(&p, "%s/%s", root, de->d_name) < 0) {
-                                log_error("Failed to allocate symlink string.");
-                                r = -ENOMEM;
-                                break;
-                        }
-
-                        if ((q = readlink_and_make_absolute(p, &dest)) < 0) {
-                                log_error("Cannot read symlink %s: %s", p, strerror(-q));
-                                free(p);
-
-                                if (r == 0)
-                                        r = q;
-                                continue;
-                        }
-
-                        if ((c = canonicalize_file_name(dest))) {
-                                /* This might fail if the destination
-                                 * is already removed */
-
-                                free(dest);
-                                dest = c;
-                        }
-
-                        path_kill_slashes(dest);
-                        if (set_get(remove_symlinks_to, dest)) {
-
-                                if (arg_verbose)
-                                        log_info("rm '%s'", p);
-
-                                if (unlink(p) < 0) {
-                                        log_error("Cannot unlink symlink %s: %m", p);
-
-                                        if (r == 0)
-                                                r = -errno;
-                                } else {
-                                        rmdir_parents(p, config_path);
-                                        path_kill_slashes(p);
-
-                                        if (!set_get(remove_symlinks_to, p)) {
-
-                                                if ((r = mark_symlink_for_removal(p)) < 0) {
-                                                        if (r == 0)
-                                                                r = q;
-                                                } else
-                                                        *deleted = true;
-                                        }
-                                }
-                        }
-
-                        free(p);
-                        free(dest);
-                }
-        }
-
-        return r;
-}
-
-static int remove_marked_symlinks(const char *config_path) {
-        int fd, r = 0;
-        bool deleted;
-
-        assert(config_path);
-
-        if (set_size(remove_symlinks_to) <= 0)
-                return 0;
-
-        if ((fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW)) < 0)
-                return -errno;
-
-        do {
-                int q;
-                deleted = false;
-
-                if ((q = remove_marked_symlinks_fd(fd, config_path, config_path, &deleted)) < 0) {
-                        if (r == 0)
-                                r = q;
-                }
-        } while (deleted);
-
-        close_nointr_nofail(fd);
-
-        return r;
-}
-
-static int create_symlink(const char *old_path, const char *new_path) {
-        int r;
-
-        assert(old_path);
-        assert(new_path);
-
-        if (arg_action == ACTION_ENABLE) {
-                char *dest;
-
-                mkdir_parents(new_path, 0755);
-
-                if (symlink(old_path, new_path) >= 0)
-                        return 0;
-
-                if (errno != EEXIST) {
-                        log_error("Cannot link %s to %s: %m", old_path, new_path);
-                        return -errno;
-                }
-
-                if ((r = readlink_and_make_absolute(new_path, &dest)) < 0) {
-
-                        if (errno == EINVAL) {
-                                log_error("Cannot link %s to %s, file exists already and is not a symlink.", old_path, new_path);
-                                return -EEXIST;
-                        }
-
-                        log_error("readlink() failed: %s", strerror(-r));
-                        return r;
-                }
-
-                if (streq(dest, old_path)) {
-                        free(dest);
-                        return 0;
-                }
-
-                if (!arg_force) {
-                        log_error("Cannot link %s to %s, symlink exists already and points to %s.", old_path, new_path, dest);
-                        free(dest);
-                        return -EEXIST;
-                }
-
-                free(dest);
-                unlink(new_path);
-
-                if (arg_verbose)
-                        log_info("ln -s '%s' '%s'", old_path, new_path);
-
-                if (symlink(old_path, new_path) >= 0)
-                        return 0;
-
-                log_error("Cannot link %s to %s: %m", old_path, new_path);
-                return -errno;
-
-        } else if (arg_action == ACTION_DISABLE) {
-                char *dest;
-
-                if ((r = mark_symlink_for_removal(old_path)) < 0)
-                        return r;
-
-                if ((r = readlink_and_make_absolute(new_path, &dest)) < 0) {
-                        if (errno == ENOENT)
-                                return 0;
-
-                        if (errno == EINVAL) {
-                                log_warning("File %s not a symlink, ignoring.", old_path);
-                                return 0;
-                        }
-
-                        log_error("readlink() failed: %s", strerror(-r));
-                        return r;
-                }
-
-                if (!streq(dest, old_path)) {
-                        log_warning("File %s not a symlink to %s but points to %s, ignoring.", new_path, old_path, dest);
-                        free(dest);
-                        return 0;
-                }
-
-
-                free(dest);
-
-                if ((r = mark_symlink_for_removal(new_path)) < 0)
-                        return r;
-
-                if (arg_verbose)
-                        log_info("rm '%s'", new_path);
-
-                if (unlink(new_path) >= 0)
-                        return 0;
-
-                log_error("Cannot unlink %s: %m", new_path);
-                return -errno;
-
-        } else if (arg_action == ACTION_TEST || arg_action == ACTION_REALIZE) {
-                char *dest;
-
-                if ((r = readlink_and_make_absolute(new_path, &dest)) < 0) {
-
-                        if (errno == ENOENT || errno == EINVAL)
-                                return 0;
-
-                        log_error("readlink() failed: %s", strerror(-r));
-                        return r;
-                }
-
-                if (streq(dest, old_path)) {
-                        free(dest);
-                        return 1;
-                }
-
-                return 0;
-        }
-
-        assert_not_reached("Unknown action.");
-}
-
-static int install_info_symlink_alias(InstallInfo *i, const char *config_path) {
-        char **s;
-        char *alias_path = NULL;
-        int r;
-
-        assert(i);
-
-        STRV_FOREACH(s, i->aliases) {
-
-                if (!unit_name_valid(*s)) {
-                        log_error("Invalid name %s.", *s);
-                        r = -EINVAL;
-                        goto finish;
-                }
-
-                free(alias_path);
-                if (!(alias_path = path_make_absolute(*s, config_path))) {
-                        log_error("Out of memory");
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                if ((r = create_symlink(i->path, alias_path)) != 0)
-                        goto finish;
-
-                if (arg_action == ACTION_DISABLE)
-                        rmdir_parents(alias_path, config_path);
-        }
-
-        r = 0;
-
-finish:
-        free(alias_path);
-
-        return r;
-}
-
-static int install_info_symlink_wants(InstallInfo *i, const char *config_path) {
-        char **s;
-        char *alias_path = NULL;
-        int r;
-
-        assert(i);
-
-        STRV_FOREACH(s, i->wanted_by) {
-                if (!unit_name_valid(*s)) {
-                        log_error("Invalid name %s.", *s);
-                        r = -EINVAL;
-                        goto finish;
-                }
-
-                free(alias_path);
-                alias_path = NULL;
-
-                if (asprintf(&alias_path, "%s/%s.wants/%s", config_path, *s, i->name) < 0) {
-                        log_error("Out of memory");
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                if ((r = create_symlink(i->path, alias_path)) != 0)
-                        goto finish;
-
-                if (arg_action == ACTION_DISABLE)
-                        rmdir_parents(alias_path, config_path);
-        }
-
-        r = 0;
-
-finish:
-        free(alias_path);
-
-        return r;
-}
-
-static int install_info_apply(LookupPaths *paths, InstallInfo *i, const char *config_path) {
-
-        const ConfigItem items[] = {
-                { "Alias",    config_parse_strv, &i->aliases,   "Install" },
-                { "WantedBy", config_parse_strv, &i->wanted_by, "Install" },
-                { "Also",     config_parse_also, NULL,          "Install" },
-
-                { NULL, NULL, NULL, NULL }
-        };
-
-        char **p;
-        char *filename = NULL;
-        FILE *f = NULL;
-        int r;
-
-        assert(paths);
-        assert(i);
-
-        STRV_FOREACH(p, paths->unit_path) {
-                int fd;
-
-                if (!(filename = path_make_absolute(i->name, *p))) {
-                        log_error("Out of memory");
-                        return -ENOMEM;
-                }
-
-                /* Ensure that we don't follow symlinks */
-                if ((fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOCTTY)) >= 0)
-                        if ((f = fdopen(fd, "re")))
-                                break;
-
-                if (errno == ELOOP) {
-                        log_error("Refusing to operate on symlinks, please pass unit names or absolute paths to unit files.");
-                        free(filename);
-                        return -errno;
-                }
-
-                if (errno != ENOENT) {
-                        log_error("Failed to open %s: %m", filename);
-                        free(filename);
-                        return -errno;
-                }
-
-                free(filename);
-                filename = NULL;
-        }
-
-        if (!f) {
-                log_error("Couldn't find %s.", i->name);
-                return -ENOENT;
-        }
-
-        i->path = filename;
-
-        if ((r = config_parse(filename, f, NULL, items, true, i)) < 0) {
-                fclose(f);
-                return r;
-        }
-
-        fclose(f);
-
-        if ((r = install_info_symlink_alias(i, config_path)) != 0)
-                return r;
-
-        if ((r = install_info_symlink_wants(i, config_path)) != 0)
-                return r;
-
-        if ((r = mark_symlink_for_removal(filename)) < 0)
-                return r;
-
-        if ((r = remove_marked_symlinks(config_path)) < 0)
-                return r;
-
-        return 0;
-}
-
-static char *get_config_path(void) {
-
-        switch (arg_where) {
-
-        case WHERE_SYSTEM:
-                return strdup(SYSTEM_CONFIG_UNIT_PATH);
-
-        case WHERE_GLOBAL:
-                return strdup(SESSION_CONFIG_UNIT_PATH);
-
-        case WHERE_SESSION: {
-                char *p;
-
-                if (session_config_home(&p) < 0)
-                        return NULL;
-
-                return p;
-        }
-
-        default:
-                assert_not_reached("Unknown config path.");
-        }
-}
-
-static int do_realize(bool enabled) {
-        DBusConnection *bus = NULL;
-        DBusError error;
-        int r, q;
-        Iterator i;
-        InstallInfo *j;
-
-        dbus_error_init(&error);
-
-        if (arg_realize == REALIZE_NO)
-                return 0;
-
-        if (arg_where == WHERE_GLOBAL) {
-                log_warning("Warning: --realize has no effect with --global.");
-                return 0;
-        }
-
-        if (arg_action == ACTION_TEST) {
-                log_warning("Warning: --realize has no effect with test.");
-                return 0;
-        }
-
-        if (arg_where == WHERE_SYSTEM && sd_booted() <= 0) {
-                log_info("systemd is not running, --realize has no effect.");
-                return 0;
-        }
-
-        if (arg_where == WHERE_SYSTEM && running_in_chroot() > 0) {
-                log_info("Running in a chroot() environment, --realize has no effect.");
-                return 0;
-        }
-
-        if ((r = bus_connect(arg_where == WHERE_SESSION ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &bus, NULL, &error)) < 0) {
-                log_error("Failed to get D-Bus connection: %s", error.message);
-                goto finish;
-        }
-
-        r = 0;
-
-        if (arg_action == ACTION_ENABLE || arg_action == ACTION_REALIZE)
-                if ((r = daemon_reload(bus)) < 0)
-                        goto finish;
-
-        if (arg_realize != REALIZE_RELOAD) {
-                HASHMAP_FOREACH(j, have_installed, i)
-                        if ((q = install_info_run(bus, j, enabled)) < 0)
-                                r = q;
-        }
-
-        if (arg_action == ACTION_DISABLE)
-                if ((q = daemon_reload(bus)) < 0)
-                        r = q;
-
-finish:
-        if (bus) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-        }
-
-        dbus_error_free(&error);
-
-        dbus_shutdown();
-        return r;
-}
-
-int main(int argc, char *argv[]) {
-        int r, retval = 1, j;
-        LookupPaths paths;
-        InstallInfo *i;
-        char *config_path = NULL;
-
-        zero(paths);
-
-        log_parse_environment();
-
-        if ((r = parse_argv(argc, argv)) < 0)
-                goto finish;
-        else if (r == 0) {
-                retval = 0;
-                goto finish;
-        }
-
-        if ((r = lookup_paths_init(&paths, arg_where == WHERE_SYSTEM ? MANAGER_SYSTEM : MANAGER_SESSION)) < 0) {
-                log_error("Failed to determine lookup paths: %s", strerror(-r));
-                goto finish;
-        }
-
-        if (!(config_path = get_config_path())) {
-                log_error("Failed to determine config path");
-                goto finish;
-        }
-
-        will_install = hashmap_new(string_hash_func, string_compare_func);
-        have_installed = hashmap_new(string_hash_func, string_compare_func);
-
-        if (!will_install || !have_installed) {
-                log_error("Failed to allocate unit sets.");
-                goto finish;
-        }
-
-        if (arg_all)
-                if (!(remove_symlinks_to = set_new(string_hash_func, string_compare_func))) {
-                        log_error("Failed to allocate symlink sets.");
-                        goto finish;
-                }
-
-        for (j = optind; j < argc; j++)
-                if ((r = install_info_add(argv[j])) < 0)
-                        goto finish;
-
-
-        while ((i = hashmap_first(will_install))) {
-                assert_se(hashmap_move_one(have_installed, will_install, i->name) == 0);
-
-                if ((r = install_info_apply(&paths, i, config_path)) != 0) {
-
-                        if (r < 0)
-                                goto finish;
-
-                        /* In test mode and found something */
-                        retval = 0;
-                        break;
-                }
-        }
-
-        if (do_realize(!retval) < 0)
-                goto finish;
-
-finish:
-        install_info_hashmap_free(will_install);
-        install_info_hashmap_free(have_installed);
-
-        set_free_free(remove_symlinks_to);
-
-        lookup_paths_free(&paths);
-
-        free(config_path);
-
-        return retval;
-}
index 667aeaeb9642cd4ee40891c745d96f522681b46c..1e3385f8604074ff59ea09939cc2be1d722da66e 100644 (file)
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 
 #include <dbus/dbus.h>
 
 
 #include <dbus/dbus.h>
 
 #include "cgroup-show.h"
 #include "cgroup-util.h"
 #include "list.h"
 #include "cgroup-show.h"
 #include "cgroup-util.h"
 #include "list.h"
+#include "path-lookup.h"
+#include "conf-parser.h"
+#include "sd-daemon.h"
 
 static const char *arg_type = NULL;
 static char **arg_property = NULL;
 static bool arg_all = false;
 static bool arg_fail = false;
 static bool arg_session = false;
 
 static const char *arg_type = NULL;
 static char **arg_property = NULL;
 static bool arg_all = false;
 static bool arg_fail = false;
 static bool arg_session = false;
-static bool arg_no_block = false;
+static bool arg_global = false;
 static bool arg_immediate = false;
 static bool arg_immediate = false;
+static bool arg_no_block = false;
 static bool arg_no_wtmp = false;
 static bool arg_no_sync = false;
 static bool arg_no_wall = false;
 static bool arg_no_wtmp = false;
 static bool arg_no_sync = false;
 static bool arg_no_wall = false;
+static bool arg_no_reload = false;
 static bool arg_dry = false;
 static bool arg_quiet = false;
 static bool arg_dry = false;
 static bool arg_quiet = false;
-static char arg_full = false;
+static bool arg_full = false;
+static bool arg_force = false;
+static bool arg_defaults = false;
 static char **arg_wall = NULL;
 static enum action {
         ACTION_INVALID,
 static char **arg_wall = NULL;
 static enum action {
         ACTION_INVALID,
@@ -86,6 +94,8 @@ static enum dot {
 
 static bool private_bus = false;
 
 
 static bool private_bus = false;
 
+static int daemon_reload(DBusConnection *bus, char **args, unsigned n);
+
 static const char *ansi_highlight(bool b) {
         static int t = -1;
 
 static const char *ansi_highlight(bool b) {
         static int t = -1;
 
@@ -687,6 +697,9 @@ static int cancel_job(DBusConnection *bus, char **args, unsigned n) {
         assert(bus);
         assert(args);
 
         assert(bus);
         assert(args);
 
+        if (n <= 1)
+                return daemon_reload(bus, args, n);
+
         for (i = 1; i < n; i++) {
                 unsigned id;
                 const char *path;
         for (i = 1; i < n; i++) {
                 unsigned id;
                 const char *path;
@@ -766,7 +779,7 @@ finish:
         return r;
 }
 
         return r;
 }
 
-static bool unit_need_daemon_reload(DBusConnection *bus, const char *unit) {
+static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
         DBusMessage *m, *reply;
         dbus_bool_t b = FALSE;
         DBusMessageIter iter, sub;
         DBusMessage *m, *reply;
         dbus_bool_t b = FALSE;
         DBusMessageIter iter, sub;
@@ -1007,7 +1020,7 @@ static int start_unit_one(
                 goto finish;
         }
 
                 goto finish;
         }
 
-        if (unit_need_daemon_reload(bus, name))
+        if (need_daemon_reload(bus, name))
                 log_warning("Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
                             arg_session ? "--session" : "--system");
 
                 log_warning("Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
                             arg_session ? "--session" : "--system");
 
@@ -2653,7 +2666,7 @@ finish:
         return r;
 }
 
         return r;
 }
 
-static int clear_jobs(DBusConnection *bus, char **args, unsigned n) {
+static int daemon_reload(DBusConnection *bus, char **args, unsigned n) {
         DBusMessage *m = NULL, *reply = NULL;
         DBusError error;
         int r;
         DBusMessage *m = NULL, *reply = NULL;
         DBusError error;
         int r;
@@ -2669,11 +2682,12 @@ static int clear_jobs(DBusConnection *bus, char **args, unsigned n) {
                 assert(arg_action == ACTION_SYSTEMCTL);
 
                 method =
                 assert(arg_action == ACTION_SYSTEMCTL);
 
                 method =
-                        streq(args[0], "clear-jobs")        ? "ClearJobs" :
-                        streq(args[0], "daemon-reload")     ? "Reload" :
+                        streq(args[0], "clear-jobs")        ||
+                        streq(args[0], "cancel")            ? "ClearJobs" :
                         streq(args[0], "daemon-reexec")     ? "Reexecute" :
                         streq(args[0], "reset-maintenance") ? "ResetMaintenance" :
                         streq(args[0], "daemon-reexec")     ? "Reexecute" :
                         streq(args[0], "reset-maintenance") ? "ResetMaintenance" :
-                                                              "Exit";
+                        streq(args[0], "daemon-exit")       ? "Exit" :
+                                                              "Reload";
         }
 
         if (!(m = dbus_message_new_method_call(
         }
 
         if (!(m = dbus_message_new_method_call(
@@ -2723,7 +2737,7 @@ static int reset_maintenance(DBusConnection *bus, char **args, unsigned n) {
         dbus_error_init(&error);
 
         if (n <= 1)
         dbus_error_init(&error);
 
         if (n <= 1)
-                return clear_jobs(bus, args, n);
+                return daemon_reload(bus, args, n);
 
         for (i = 1; i < n; i++) {
 
 
         for (i = 1; i < n; i++) {
 
@@ -2917,6 +2931,691 @@ finish:
         return r;
 }
 
         return r;
 }
 
+typedef struct {
+        char *name;
+        char *path;
+
+        char **aliases;
+        char **wanted_by;
+} InstallInfo;
+
+static Hashmap *will_install = NULL, *have_installed = NULL;
+static Set *remove_symlinks_to = NULL;
+
+static void install_info_free(InstallInfo *i) {
+        assert(i);
+
+        free(i->name);
+        free(i->path);
+        strv_free(i->aliases);
+        strv_free(i->wanted_by);
+        free(i);
+}
+
+static void install_info_hashmap_free(Hashmap *m) {
+        InstallInfo *i;
+
+        while ((i = hashmap_steal_first(m)))
+                install_info_free(i);
+
+        hashmap_free(m);
+}
+
+static bool unit_name_valid(const char *name) {
+
+        /* This is a minimal version of unit_name_valid() from
+         * unit-name.c */
+
+        if (!*name)
+                return false;
+
+        if (ignore_file(name))
+                return false;
+
+        return true;
+}
+
+static int install_info_add(const char *name) {
+        InstallInfo *i;
+        int r;
+
+        assert(will_install);
+
+        if (!unit_name_valid(name))
+                return -EINVAL;
+
+        if (hashmap_get(have_installed, name) ||
+            hashmap_get(will_install, name))
+                return 0;
+
+        if (!(i = new0(InstallInfo, 1))) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
+        if (!(i->name = strdup(name))) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
+        if ((r = hashmap_put(will_install, i->name, i)) < 0)
+                goto fail;
+
+        return 0;
+
+fail:
+        if (i)
+                install_info_free(i);
+
+        return r;
+}
+
+static int config_parse_also(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        char *w;
+        size_t l;
+        char *state;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+                char *n;
+                int r;
+
+                if (!(n = strndup(w, l)))
+                        return -ENOMEM;
+
+                r = install_info_add(n);
+                free(n);
+
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int mark_symlink_for_removal(const char *p) {
+        char *n;
+        int r;
+
+        assert(p);
+        assert(path_is_absolute(p));
+
+        if (!remove_symlinks_to)
+                return 0;
+
+        if (!(n = strdup(p)))
+                return -ENOMEM;
+
+        path_kill_slashes(n);
+
+        if ((r = set_put(remove_symlinks_to, n)) < 0) {
+                free(n);
+                return r == -EEXIST ? 0 : r;
+        }
+
+        return 0;
+}
+
+static int remove_marked_symlinks_fd(int fd, const char *config_path, const char *root, bool *deleted) {
+        int r = 0;
+        DIR *d;
+        struct dirent *de;
+
+        assert(fd >= 0);
+        assert(root);
+        assert(deleted);
+
+        if (!(d = fdopendir(fd))) {
+                close_nointr_nofail(fd);
+                return -errno;
+        }
+
+        rewinddir(d);
+
+        while ((de = readdir(d))) {
+                bool is_dir = false, is_link = false;
+
+                if (ignore_file(de->d_name))
+                        continue;
+
+                if (de->d_type == DT_LNK)
+                        is_link = true;
+                else if (de->d_type == DT_DIR)
+                        is_dir = true;
+                else if (de->d_type == DT_UNKNOWN) {
+                        struct stat st;
+
+                        if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
+                                log_error("Failed to stat %s/%s: %m", root, de->d_name);
+
+                                if (r == 0)
+                                        r = -errno;
+                                continue;
+                        }
+
+                        is_link = S_ISLNK(st.st_mode);
+                        is_dir = S_ISDIR(st.st_mode);
+                } else
+                        continue;
+
+                if (is_dir) {
+                        int nfd, q;
+                        char *p;
+
+                        if ((nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW)) < 0) {
+                                log_error("Failed to open %s/%s: %m", root, de->d_name);
+
+                                if (r == 0)
+                                        r = -errno;
+                                continue;
+                        }
+
+                        if (asprintf(&p, "%s/%s", root, de->d_name) < 0) {
+                                log_error("Failed to allocate directory string.");
+                                close_nointr_nofail(nfd);
+                                r = -ENOMEM;
+                                break;
+                        }
+
+                        /* This will close nfd, regardless whether it succeeds or not */
+                        q = remove_marked_symlinks_fd(nfd, config_path, p, deleted);
+                        free(p);
+
+                        if (r == 0)
+                                q = r;
+
+                } else if (is_link) {
+                        char *p, *dest, *c;
+                        int q;
+
+                        if (asprintf(&p, "%s/%s", root, de->d_name) < 0) {
+                                log_error("Failed to allocate symlink string.");
+                                r = -ENOMEM;
+                                break;
+                        }
+
+                        if ((q = readlink_and_make_absolute(p, &dest)) < 0) {
+                                log_error("Cannot read symlink %s: %s", p, strerror(-q));
+                                free(p);
+
+                                if (r == 0)
+                                        r = q;
+                                continue;
+                        }
+
+                        if ((c = canonicalize_file_name(dest))) {
+                                /* This might fail if the destination
+                                 * is already removed */
+
+                                free(dest);
+                                dest = c;
+                        }
+
+                        path_kill_slashes(dest);
+                        if (set_get(remove_symlinks_to, dest)) {
+
+                                if (!arg_quiet)
+                                        log_info("rm '%s'", p);
+
+                                if (unlink(p) < 0) {
+                                        log_error("Cannot unlink symlink %s: %m", p);
+
+                                        if (r == 0)
+                                                r = -errno;
+                                } else {
+                                        rmdir_parents(p, config_path);
+                                        path_kill_slashes(p);
+
+                                        if (!set_get(remove_symlinks_to, p)) {
+
+                                                if ((r = mark_symlink_for_removal(p)) < 0) {
+                                                        if (r == 0)
+                                                                r = q;
+                                                } else
+                                                        *deleted = true;
+                                        }
+                                }
+                        }
+
+                        free(p);
+                        free(dest);
+                }
+        }
+
+        closedir(d);
+
+        return r;
+}
+
+static int remove_marked_symlinks(const char *config_path) {
+        int fd, r = 0;
+        bool deleted;
+
+        assert(config_path);
+
+        if (set_size(remove_symlinks_to) <= 0)
+                return 0;
+
+        if ((fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW)) < 0)
+                return -errno;
+
+        do {
+                int q, cfd;
+                deleted = false;
+
+                if ((cfd = dup(fd)) < 0) {
+                        r = -errno;
+                        break;
+                }
+
+                /* This takes possession of cfd and closes it */
+                if ((q = remove_marked_symlinks_fd(cfd, config_path, config_path, &deleted)) < 0) {
+                        if (r == 0)
+                                r = q;
+                }
+        } while (deleted);
+
+        close_nointr_nofail(fd);
+
+        return r;
+}
+
+static int create_symlink(const char *verb, const char *old_path, const char *new_path) {
+        int r;
+
+        assert(old_path);
+        assert(new_path);
+        assert(verb);
+
+        if (streq(verb, "enable")) {
+                char *dest;
+
+                mkdir_parents(new_path, 0755);
+
+                if (symlink(old_path, new_path) >= 0) {
+
+                        if (!arg_quiet)
+                                log_info("ln -s '%s' '%s'", old_path, new_path);
+
+                        return 0;
+                }
+
+                if (errno != EEXIST) {
+                        log_error("Cannot link %s to %s: %m", old_path, new_path);
+                        return -errno;
+                }
+
+                if ((r = readlink_and_make_absolute(new_path, &dest)) < 0) {
+
+                        if (errno == EINVAL) {
+                                log_error("Cannot link %s to %s, file exists already and is not a symlink.", old_path, new_path);
+                                return -EEXIST;
+                        }
+
+                        log_error("readlink() failed: %s", strerror(-r));
+                        return r;
+                }
+
+                if (streq(dest, old_path)) {
+                        free(dest);
+                        return 0;
+                }
+
+                if (!arg_force) {
+                        log_error("Cannot link %s to %s, symlink exists already and points to %s.", old_path, new_path, dest);
+                        free(dest);
+                        return -EEXIST;
+                }
+
+                free(dest);
+                unlink(new_path);
+
+                if (!arg_quiet)
+                        log_info("ln -s '%s' '%s'", old_path, new_path);
+
+                if (symlink(old_path, new_path) >= 0)
+                        return 0;
+
+                log_error("Cannot link %s to %s: %m", old_path, new_path);
+                return -errno;
+
+        } else if (streq(verb, "disable")) {
+                char *dest;
+
+                if ((r = mark_symlink_for_removal(old_path)) < 0)
+                        return r;
+
+                if ((r = readlink_and_make_absolute(new_path, &dest)) < 0) {
+                        if (errno == ENOENT)
+                                return 0;
+
+                        if (errno == EINVAL) {
+                                log_warning("File %s not a symlink, ignoring.", old_path);
+                                return 0;
+                        }
+
+                        log_error("readlink() failed: %s", strerror(-r));
+                        return r;
+                }
+
+                if (!streq(dest, old_path)) {
+                        log_warning("File %s not a symlink to %s but points to %s, ignoring.", new_path, old_path, dest);
+                        free(dest);
+                        return 0;
+                }
+
+                free(dest);
+
+                if ((r = mark_symlink_for_removal(new_path)) < 0)
+                        return r;
+
+                if (!arg_quiet)
+                        log_info("rm '%s'", new_path);
+
+                if (unlink(new_path) >= 0)
+                        return 0;
+
+                log_error("Cannot unlink %s: %m", new_path);
+                return -errno;
+
+        } else if (streq(verb, "is-enabled")) {
+                char *dest;
+
+                if ((r = readlink_and_make_absolute(new_path, &dest)) < 0) {
+
+                        if (errno == ENOENT || errno == EINVAL)
+                                return 0;
+
+                        log_error("readlink() failed: %s", strerror(-r));
+                        return r;
+                }
+
+                if (streq(dest, old_path)) {
+                        free(dest);
+                        return 1;
+                }
+
+                return 0;
+        }
+
+        assert_not_reached("Unknown action.");
+}
+
+static int install_info_symlink_alias(const char *verb, InstallInfo *i, const char *config_path) {
+        char **s;
+        char *alias_path = NULL;
+        int r;
+
+        assert(verb);
+        assert(i);
+        assert(config_path);
+
+        STRV_FOREACH(s, i->aliases) {
+
+                if (!unit_name_valid(*s)) {
+                        log_error("Invalid name %s.", *s);
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                free(alias_path);
+                if (!(alias_path = path_make_absolute(*s, config_path))) {
+                        log_error("Out of memory");
+                        r = -ENOMEM;
+                        goto finish;
+                }
+
+                if ((r = create_symlink(verb, i->path, alias_path)) != 0)
+                        goto finish;
+
+                if (streq(verb, "disable"))
+                        rmdir_parents(alias_path, config_path);
+        }
+
+        r = 0;
+
+finish:
+        free(alias_path);
+
+        return r;
+}
+
+static int install_info_symlink_wants(const char *verb, InstallInfo *i, const char *config_path) {
+        char **s;
+        char *alias_path = NULL;
+        int r;
+
+        assert(verb);
+        assert(i);
+        assert(config_path);
+
+        STRV_FOREACH(s, i->wanted_by) {
+                if (!unit_name_valid(*s)) {
+                        log_error("Invalid name %s.", *s);
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                free(alias_path);
+                alias_path = NULL;
+
+                if (asprintf(&alias_path, "%s/%s.wants/%s", config_path, *s, i->name) < 0) {
+                        log_error("Out of memory");
+                        r = -ENOMEM;
+                        goto finish;
+                }
+
+                if ((r = create_symlink(verb, i->path, alias_path)) != 0)
+                        goto finish;
+
+                if (streq(verb, "disable"))
+                        rmdir_parents(alias_path, config_path);
+        }
+
+        r = 0;
+
+finish:
+        free(alias_path);
+
+        return r;
+}
+
+static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo *i, const char *config_path) {
+
+        const ConfigItem items[] = {
+                { "Alias",    config_parse_strv, &i->aliases,   "Install" },
+                { "WantedBy", config_parse_strv, &i->wanted_by, "Install" },
+                { "Also",     config_parse_also, NULL,          "Install" },
+
+                { NULL, NULL, NULL, NULL }
+        };
+
+        char **p;
+        char *filename = NULL;
+        FILE *f = NULL;
+        int r;
+
+        assert(paths);
+        assert(i);
+
+        STRV_FOREACH(p, paths->unit_path) {
+                int fd;
+
+                if (!(filename = path_make_absolute(i->name, *p))) {
+                        log_error("Out of memory");
+                        return -ENOMEM;
+                }
+
+                /* Ensure that we don't follow symlinks */
+                if ((fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOCTTY)) >= 0)
+                        if ((f = fdopen(fd, "re")))
+                                break;
+
+                if (errno == ELOOP) {
+                        log_error("Refusing to operate on symlinks, please pass unit names or absolute paths to unit files.");
+                        free(filename);
+                        return -errno;
+                }
+
+                if (errno != ENOENT) {
+                        log_error("Failed to open %s: %m", filename);
+                        free(filename);
+                        return -errno;
+                }
+
+                free(filename);
+                filename = NULL;
+        }
+
+        if (!f) {
+                log_error("Couldn't find %s.", i->name);
+                return -ENOENT;
+        }
+
+        i->path = filename;
+
+        if ((r = config_parse(filename, f, NULL, items, true, i)) < 0) {
+                fclose(f);
+                return r;
+        }
+
+        fclose(f);
+
+        if ((r = install_info_symlink_alias(verb, i, config_path)) != 0)
+                return r;
+
+        if ((r = install_info_symlink_wants(verb, i, config_path)) != 0)
+                return r;
+
+        if ((r = mark_symlink_for_removal(filename)) < 0)
+                return r;
+
+        if ((r = remove_marked_symlinks(config_path)) < 0)
+                return r;
+
+        return 0;
+}
+
+static char *get_config_path(void) {
+
+        if (arg_session && arg_global)
+                return strdup(SESSION_CONFIG_UNIT_PATH);
+
+        if (arg_session) {
+                char *p;
+
+                if (session_config_home(&p) < 0)
+                        return NULL;
+
+                return p;
+        }
+
+        return strdup(SYSTEM_CONFIG_UNIT_PATH);
+}
+
+static int enable_unit(DBusConnection *bus, char **args, unsigned n) {
+        DBusError error;
+        int r;
+        LookupPaths paths;
+        char *config_path = NULL;
+        unsigned j;
+        InstallInfo *i;
+        const char *verb = args[0];
+
+        dbus_error_init(&error);
+
+        zero(paths);
+        if ((r = lookup_paths_init(&paths, arg_session ? MANAGER_SESSION : MANAGER_SYSTEM)) < 0) {
+                log_error("Failed to determine lookup paths: %s", strerror(-r));
+                goto finish;
+        }
+
+        if (!(config_path = get_config_path())) {
+                log_error("Failed to determine config path");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        will_install = hashmap_new(string_hash_func, string_compare_func);
+        have_installed = hashmap_new(string_hash_func, string_compare_func);
+
+        if (!will_install || !have_installed) {
+                log_error("Failed to allocate unit sets.");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        if (!arg_defaults && streq(verb, "disable"))
+                if (!(remove_symlinks_to = set_new(string_hash_func, string_compare_func))) {
+                        log_error("Failed to allocate symlink sets.");
+                        r = -ENOMEM;
+                        goto finish;
+                }
+
+        for (j = 1; j < n; j++)
+                if ((r = install_info_add(args[j])) < 0)
+                        goto finish;
+
+        while ((i = hashmap_first(will_install))) {
+                int q;
+
+                assert_se(hashmap_move_one(have_installed, will_install, i->name) == 0);
+
+                if ((q = install_info_apply(verb, &paths, i, config_path)) != 0) {
+
+                        if (q < 0) {
+                                if (r == 0)
+                                        r = q;
+                                goto finish;
+                        }
+
+                        /* In test mode and found something */
+                        r = 1;
+                        break;
+                }
+        }
+
+        if (streq(verb, "is-enabled"))
+                r = r > 0 ? 0 : -ENOENT;
+        else if (bus &&
+                 /* Don't try to reload anything if the user asked us to not do this */
+                 !arg_no_reload &&
+                 /* Don't try to reload anything when updating a unit globally */
+                 !arg_global &&
+                 /* Don't try to reload anything if we are called for system changes but the system wasn't booted with systemd */
+                 (arg_session || sd_booted() > 0) &&
+                 /* Don't try to reload anything if we are running in a chroot environment */
+                 (arg_session || running_in_chroot() <= 0) ) {
+                int q;
+
+                if ((q = daemon_reload(bus, args, n)) < 0)
+                        r = q;
+        }
+
+finish:
+        install_info_hashmap_free(will_install);
+        install_info_hashmap_free(have_installed);
+
+        set_free_free(remove_symlinks_to);
+
+        lookup_paths_free(&paths);
+
+        free(config_path);
+
+        return r;
+}
+
 static int systemctl_help(void) {
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
 static int systemctl_help(void) {
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
@@ -2925,20 +3624,25 @@ static int systemctl_help(void) {
                "  -t --type=TYPE     List only units of a particular type\n"
                "  -p --property=NAME Show only properties by this name\n"
                "  -a --all           Show all units/properties, including dead/empty ones\n"
                "  -t --type=TYPE     List only units of a particular type\n"
                "  -p --property=NAME Show only properties by this name\n"
                "  -a --all           Show all units/properties, including dead/empty ones\n"
-               "     --full          Don't ellipsize unit names.\n"
-               "     --fail          When installing a new job, fail if conflicting jobs are\n"
+               "     --full          Don't ellipsize unit names on output\n"
+               "     --fail          When queueing a new job, fail if conflicting jobs are\n"
                "                     pending\n"
                "                     pending\n"
+               "  -q --quiet         Suppress output\n"
+               "     --no-block      Do not wait until operation finished\n"
                "     --system        Connect to system bus\n"
                "     --session       Connect to session bus\n"
                "     --order         When generating graph for dot, show only order\n"
                "     --system        Connect to system bus\n"
                "     --session       Connect to session bus\n"
                "     --order         When generating graph for dot, show only order\n"
-               "     --require        When generating graph for dot, show only requirement\n"
-               "  -q --quiet         Suppress output\n"
-               "     --no-block      Do not wait until operation finished\n"
-               "     --no-wall       Don't send wall message before halt/power-off/reboot\n\n"
+               "     --require       When generating graph for dot, show only requirement\n"
+               "     --no-wall       Don't send wall message before halt/power-off/reboot\n"
+               "     --global        Enable/disable unit files globally\n"
+               "     --no-reload     When enabling/disabling unit files, don't reload daemon\n"
+               "                     configuration\n"
+               "     --force         When enabling unit files, override existing symlinks\n"
+               "     --defaults      When disabling unit files, remove default symlinks only\n\n"
                "Commands:\n"
                "  list-units                      List units\n"
                "Commands:\n"
                "  list-units                      List units\n"
-               "  start [NAME...]                 Start one or more units\n"
-               "  stop [NAME...]                  Stop one or more units\n"
+               "  start [NAME...]                 Start (activate) one or more units\n"
+               "  stop [NAME...]                  Stop (deactivate) one or more units\n"
                "  reload [NAME...]                Reload one or more units\n"
                "  restart [NAME...]               Start or restart one or more units\n"
                "  try-restart [NAME...]           Restart one or more units if active\n"
                "  reload [NAME...]                Reload one or more units\n"
                "  restart [NAME...]               Start or restart one or more units\n"
                "  try-restart [NAME...]           Restart one or more units if active\n"
@@ -2947,16 +3651,18 @@ static int systemctl_help(void) {
                "  reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
                "                                  otherwise restart if active\n"
                "  isolate [NAME]                  Start one unit and stop all others\n"
                "  reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
                "                                  otherwise restart if active\n"
                "  isolate [NAME]                  Start one unit and stop all others\n"
-               "  check [NAME...]                 Check whether units are active\n"
-               "  status [NAME...]                Show status of one or more units\n"
+               "  is-active [NAME...]             Check whether units are active\n"
+               "  status [NAME...]                Show runtime status of one or more units\n"
                "  show [NAME...|JOB...]           Show properties of one or more\n"
                "  show [NAME...|JOB...]           Show properties of one or more\n"
-               "                                  units/jobs/manager\n"
-               "  reset-maintenance [NAME...]     Reset maintenance state for all, one\n"
+               "                                  units/jobs or the manager\n"
+               "  reset-maintenance [NAME...]     Reset maintenance state for all, one,\n"
                "                                  or more units\n"
                "                                  or more units\n"
+               "  enable [NAME...]                Enable one or more unit files\n"
+               "  disable [NAME...]               Disable one or more unit files\n"
+               "  is-enabled [NAME...]            Check whether unit files are enabled\n"
                "  load [NAME...]                  Load one or more units\n"
                "  list-jobs                       List jobs\n"
                "  load [NAME...]                  Load one or more units\n"
                "  list-jobs                       List jobs\n"
-               "  cancel [JOB...]                 Cancel one or more jobs\n"
-               "  clear-jobs                      Cancel all jobs\n"
+               "  cancel [JOB...]                 Cancel all, one, or more jobs\n"
                "  monitor                         Monitor unit/job changes\n"
                "  dump                            Dump server status\n"
                "  dot                             Dump dependency graph for dot(1)\n"
                "  monitor                         Monitor unit/job changes\n"
                "  dump                            Dump server status\n"
                "  dot                             Dump dependency graph for dot(1)\n"
@@ -3050,28 +3756,36 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_FAIL = 0x100,
                 ARG_SESSION,
                 ARG_SYSTEM,
                 ARG_FAIL = 0x100,
                 ARG_SESSION,
                 ARG_SYSTEM,
+                ARG_GLOBAL,
                 ARG_NO_BLOCK,
                 ARG_NO_WALL,
                 ARG_ORDER,
                 ARG_REQUIRE,
                 ARG_NO_BLOCK,
                 ARG_NO_WALL,
                 ARG_ORDER,
                 ARG_REQUIRE,
-                ARG_FULL
+                ARG_FULL,
+                ARG_FORCE,
+                ARG_NO_RELOAD,
+                ARG_DEFAULTS
         };
 
         static const struct option options[] = {
         };
 
         static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'          },
-                { "type",      required_argument, NULL, 't'          },
-                { "property",  required_argument, NULL, 'p'          },
-                { "all",       no_argument,       NULL, 'a'          },
-                { "full",      no_argument,       NULL, ARG_FULL     },
-                { "fail",      no_argument,       NULL, ARG_FAIL     },
-                { "session",   no_argument,       NULL, ARG_SESSION  },
-                { "system",    no_argument,       NULL, ARG_SYSTEM   },
-                { "no-block",  no_argument,       NULL, ARG_NO_BLOCK },
-                { "no-wall",   no_argument,       NULL, ARG_NO_WALL  },
-                { "quiet",     no_argument,       NULL, 'q'          },
-                { "order",     no_argument,       NULL, ARG_ORDER    },
-                { "require",   no_argument,       NULL, ARG_REQUIRE  },
-                { NULL,        0,                 NULL, 0            }
+                { "help",      no_argument,       NULL, 'h'           },
+                { "type",      required_argument, NULL, 't'           },
+                { "property",  required_argument, NULL, 'p'           },
+                { "all",       no_argument,       NULL, 'a'           },
+                { "full",      no_argument,       NULL, ARG_FULL      },
+                { "fail",      no_argument,       NULL, ARG_FAIL      },
+                { "session",   no_argument,       NULL, ARG_SESSION   },
+                { "system",    no_argument,       NULL, ARG_SYSTEM    },
+                { "global",    no_argument,       NULL, ARG_GLOBAL    },
+                { "no-block",  no_argument,       NULL, ARG_NO_BLOCK  },
+                { "no-wall",   no_argument,       NULL, ARG_NO_WALL   },
+                { "quiet",     no_argument,       NULL, 'q'           },
+                { "order",     no_argument,       NULL, ARG_ORDER     },
+                { "require",   no_argument,       NULL, ARG_REQUIRE   },
+                { "force",     no_argument,       NULL, ARG_FORCE     },
+                { "no-reload", no_argument,       NULL, ARG_NO_RELOAD },
+                { "defaults",   no_argument,      NULL, ARG_DEFAULTS  },
+                { NULL,        0,                 NULL, 0             }
         };
 
         int c;
         };
 
         int c;
@@ -3147,6 +3861,23 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_quiet = true;
                         break;
 
                         arg_quiet = true;
                         break;
 
+                case ARG_FORCE:
+                        arg_force = true;
+                        break;
+
+                case ARG_NO_RELOAD:
+                        arg_no_reload = true;
+                        break;
+
+                case ARG_GLOBAL:
+                        arg_global = true;
+                        arg_session = true;
+                        break;
+
+                case ARG_DEFAULTS:
+                        arg_defaults = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
                 case '?':
                         return -EINVAL;
 
@@ -3638,7 +4369,7 @@ static int talk_initctl(void) {
         return 1;
 }
 
         return 1;
 }
 
-static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
+static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
 
         static const struct {
                 const char* verb;
 
         static const struct {
                 const char* verb;
@@ -3650,42 +4381,46 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
                 const int argc;
                 int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
         } verbs[] = {
                 const int argc;
                 int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
         } verbs[] = {
-                { "list-units",        LESS,  1, list_units      },
-                { "list-jobs",         EQUAL, 1, list_jobs       },
-                { "clear-jobs",        EQUAL, 1, clear_jobs      },
-                { "load",              MORE,  2, load_unit       },
-                { "cancel",            MORE,  2, cancel_job      },
-                { "start",             MORE,  2, start_unit      },
-                { "stop",              MORE,  2, start_unit      },
-                { "reload",            MORE,  2, start_unit      },
-                { "restart",           MORE,  2, start_unit      },
-                { "try-restart",       MORE,  2, start_unit      },
-                { "reload-or-restart", MORE,  2, start_unit      },
-                { "reload-or-try-restart", MORE, 2, start_unit   },
-                { "force-reload",      MORE,  2, start_unit      }, /* For compatibility with SysV */
-                { "condrestart",       MORE,  2, start_unit      }, /* For compatibility with RH */
-                { "isolate",           EQUAL, 2, start_unit      },
-                { "check",             MORE,  2, check_unit      },
-                { "show",              MORE,  1, show            },
-                { "status",            MORE,  2, show            },
-                { "monitor",           EQUAL, 1, monitor         },
-                { "dump",              EQUAL, 1, dump            },
-                { "dot",               EQUAL, 1, dot             },
-                { "snapshot",          LESS,  2, snapshot        },
-                { "delete",            MORE,  2, delete_snapshot },
-                { "daemon-reload",     EQUAL, 1, clear_jobs      },
-                { "daemon-reexec",     EQUAL, 1, clear_jobs      },
-                { "daemon-exit",       EQUAL, 1, clear_jobs      },
-                { "show-environment",  EQUAL, 1, show_enviroment },
-                { "set-environment",   MORE,  2, set_environment },
-                { "unset-environment", MORE,  2, set_environment },
-                { "halt",              EQUAL, 1, start_special   },
-                { "poweroff",          EQUAL, 1, start_special   },
-                { "reboot",            EQUAL, 1, start_special   },
-                { "default",           EQUAL, 1, start_special   },
-                { "rescue",            EQUAL, 1, start_special   },
-                { "emergency",         EQUAL, 1, start_special   },
-                { "reset-maintenance", MORE,  1, reset_maintenance },
+                { "list-units",            LESS,  1, list_units        },
+                { "list-jobs",             EQUAL, 1, list_jobs         },
+                { "clear-jobs",            EQUAL, 1, daemon_reload     },
+                { "load",                  MORE,  2, load_unit         },
+                { "cancel",                MORE,  2, cancel_job        },
+                { "start",                 MORE,  2, start_unit        },
+                { "stop",                  MORE,  2, start_unit        },
+                { "reload",                MORE,  2, start_unit        },
+                { "restart",               MORE,  2, start_unit        },
+                { "try-restart",           MORE,  2, start_unit        },
+                { "reload-or-restart",     MORE,  2, start_unit        },
+                { "reload-or-try-restart", MORE,  2, start_unit        },
+                { "force-reload",          MORE,  2, start_unit        }, /* For compatibility with SysV */
+                { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
+                { "isolate",               EQUAL, 2, start_unit        },
+                { "is-active",             MORE,  2, check_unit        },
+                { "check",                 MORE,  2, check_unit        },
+                { "show",                  MORE,  1, show              },
+                { "status",                MORE,  2, show              },
+                { "monitor",               EQUAL, 1, monitor           },
+                { "dump",                  EQUAL, 1, dump              },
+                { "dot",                   EQUAL, 1, dot               },
+                { "snapshot",              LESS,  2, snapshot          },
+                { "delete",                MORE,  2, delete_snapshot   },
+                { "daemon-reload",         EQUAL, 1, daemon_reload     },
+                { "daemon-reexec",         EQUAL, 1, daemon_reload     },
+                { "daemon-exit",           EQUAL, 1, daemon_reload     },
+                { "show-environment",      EQUAL, 1, show_enviroment   },
+                { "set-environment",       MORE,  2, set_environment   },
+                { "unset-environment",     MORE,  2, set_environment   },
+                { "halt",                  EQUAL, 1, start_special     },
+                { "poweroff",              EQUAL, 1, start_special     },
+                { "reboot",                EQUAL, 1, start_special     },
+                { "default",               EQUAL, 1, start_special     },
+                { "rescue",                EQUAL, 1, start_special     },
+                { "emergency",             EQUAL, 1, start_special     },
+                { "reset-maintenance",     MORE,  1, reset_maintenance },
+                { "enable",                MORE,  2, enable_unit       },
+                { "disable",               MORE,  2, enable_unit       },
+                { "is-enabled",            MORE,  2, enable_unit       }
         };
 
         int left;
         };
 
         int left;
@@ -3694,6 +4429,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
         assert(bus);
         assert(argc >= 0);
         assert(argv);
         assert(bus);
         assert(argc >= 0);
         assert(argv);
+        assert(error);
 
         left = argc - optind;
 
 
         left = argc - optind;
 
@@ -3746,6 +4482,15 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
                 assert_not_reached("Unknown comparison operator.");
         }
 
                 assert_not_reached("Unknown comparison operator.");
         }
 
+        /* Require a bus connection for all operations but
+         * enable/disable */
+        if (!streq(verbs[i].verb, "enable") &&
+            !streq(verbs[i].verb, "disable") &&
+            !bus) {
+                log_error("Failed to get D-Bus connection: %s", error->message);
+                return -EIO;
+        }
+
         return verbs[i].dispatch(bus, argv + optind, left);
 }
 
         return verbs[i].dispatch(bus, argv + optind, left);
 }
 
@@ -3754,7 +4499,7 @@ static int reload_with_fallback(DBusConnection *bus) {
 
         if (bus) {
                 /* First, try systemd via D-Bus. */
 
         if (bus) {
                 /* First, try systemd via D-Bus. */
-                if ((r = clear_jobs(bus, NULL, 0)) > 0)
+                if ((r = daemon_reload(bus, NULL, 0)) > 0)
                         return 0;
         }
 
                         return 0;
         }
 
@@ -3890,13 +4635,7 @@ int main(int argc, char*argv[]) {
         switch (arg_action) {
 
         case ACTION_SYSTEMCTL: {
         switch (arg_action) {
 
         case ACTION_SYSTEMCTL: {
-
-                if (!bus) {
-                        log_error("Failed to get D-Bus connection: %s", error.message);
-                        goto finish;
-                }
-
-                retval = systemctl_main(bus, argc, argv) < 0;
+                retval = systemctl_main(bus, argc, argv, &error) < 0;
                 break;
         }
 
                 break;
         }