[systemd-commits] 12 commits - bootstrap.sh fixme man/systemctl.xml src/automount.c src/dbus.c src/dbus.h src/dbus-socket.c src/dbus-unit.h src/execute.c src/execute.h src/initctl.c src/job.c src/load-fragment.c src/manager.c src/manager.h src/missing.h src/mount.c src/path.c src/service.c src/snapshot.c src/snapshot.h src/socket.c src/socket.h src/socket-util.c src/socket-util.h src/swap.c src/systemadm.vala src/systemctl.c src/timer.c src/unit.c src/unit.h src/util.c src/util.h

Lennart Poettering lennart at kemper.freedesktop.org
Thu Jul 1 05:35:18 PDT 2010


 bootstrap.sh        |    2 
 fixme               |    8 +-
 man/systemctl.xml   |   44 +++++++++--
 src/automount.c     |    2 
 src/dbus-socket.c   |   18 ++++
 src/dbus-unit.h     |    8 +-
 src/dbus.c          |   16 ++++
 src/dbus.h          |    1 
 src/execute.c       |   12 +--
 src/execute.h       |    4 -
 src/initctl.c       |    2 
 src/job.c           |   15 ++-
 src/load-fragment.c |   36 +++++++++
 src/manager.c       |    4 -
 src/manager.h       |    2 
 src/missing.h       |   12 +++
 src/mount.c         |    8 +-
 src/path.c          |    2 
 src/service.c       |    6 -
 src/snapshot.c      |   23 +++++
 src/snapshot.h      |    1 
 src/socket-util.c   |    7 +
 src/socket-util.h   |    1 
 src/socket.c        |  111 +++++++++++++++++++++++++++-
 src/socket.h        |   25 ++++--
 src/swap.c          |    2 
 src/systemadm.vala  |   46 +++++------
 src/systemctl.c     |  206 +++++++++++++++++++++++++++++++++++++++++++++-------
 src/timer.c         |    4 -
 src/unit.c          |   34 ++++++--
 src/unit.h          |   21 +++--
 src/util.c          |   12 ++-
 src/util.h          |   12 ++-
 33 files changed, 577 insertions(+), 130 deletions(-)

New commits:
commit 51cfdda7e2132e0d4a39645840608ba7028073dd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 04:14:57 2010 +0200

    systemadm: update signal connection for new vala

diff --git a/src/systemadm.vala b/src/systemadm.vala
index 9e4a2a2..65a58b7 100644
--- a/src/systemadm.vala
+++ b/src/systemadm.vala
@@ -107,7 +107,7 @@ public class MainWindow : Window {
                 position = WindowPosition.CENTER;
                 set_default_size(1000, 700);
                 set_border_width(12);
-                destroy += Gtk.main_quit;
+                destroy.connect(Gtk.main_quit);
 
                 Notebook notebook = new Notebook();
                 add(notebook);
@@ -135,15 +135,15 @@ public class MainWindow : Window {
                 unit_type_combo_box.append_text("Targets");
                 unit_type_combo_box.append_text("Snapshots");
                 unit_type_combo_box.set_active(1);
-                unit_type_combo_box.changed += unit_type_changed;
+                unit_type_combo_box.changed.connect(unit_type_changed);
 
                 unit_load_entry = new Entry();
                 unit_load_button = new Button.with_mnemonic("_Load");
                 unit_load_button.set_sensitive(false);
 
-                unit_load_entry.changed += on_unit_load_entry_changed;
-                unit_load_entry.activate += on_unit_load;
-                unit_load_button.clicked += on_unit_load;
+                unit_load_entry.changed.connect(on_unit_load_entry_changed);
+                unit_load_entry.activate.connect(on_unit_load);
+                unit_load_button.clicked.connect(on_unit_load);
 
                 Box unit_load_hbox = new HBox(false, 6);
                 unit_load_hbox.pack_start(unit_load_entry, false, true, 0);
@@ -152,8 +152,8 @@ public class MainWindow : Window {
                 server_snapshot_button = new Button.with_mnemonic("Take S_napshot");
                 server_reload_button = new Button.with_mnemonic("Reload _Configuration");
 
-                server_snapshot_button.clicked += on_server_snapshot;
-                server_reload_button.clicked += on_server_reload;
+                server_snapshot_button.clicked.connect(on_server_snapshot);
+                server_reload_button.clicked.connect(on_server_reload);
 
                 type_hbox.pack_end(server_snapshot_button, false, true, 0);
                 type_hbox.pack_end(server_reload_button, false, true, 0);
@@ -169,8 +169,8 @@ public class MainWindow : Window {
                 unit_view = new TreeView.with_model(unit_model_filter);
                 job_view = new TreeView.with_model(job_model);
 
-                unit_view.cursor_changed += unit_changed;
-                job_view.cursor_changed += job_changed;
+                unit_view.cursor_changed.connect(unit_changed);
+                job_view.cursor_changed.connect(job_changed);
 
                 unit_view.insert_column_with_attributes(-1, "Load State", new CellRendererText(), "text", 2);
                 unit_view.insert_column_with_attributes(-1, "Active State", new CellRendererText(), "text", 3);
@@ -215,7 +215,7 @@ public class MainWindow : Window {
 
                 unit_dependency_label.set_track_visited_links(false);
                 unit_dependency_label.set_selectable(false);
-                unit_dependency_label.activate_link += on_activate_link;
+                unit_dependency_label.activate_link.connect(on_activate_link);
 
                 unit_fragment_path_label.set_track_visited_links(false);
 
@@ -276,10 +276,10 @@ public class MainWindow : Window {
                 reload_button = new Button.with_mnemonic("_Reload");
                 restart_button = new Button.with_mnemonic("Res_tart");
 
-                start_button.clicked += on_start;
-                stop_button.clicked += on_stop;
-                reload_button.clicked += on_reload;
-                restart_button.clicked += on_restart;
+                start_button.clicked.connect(on_start);
+                stop_button.clicked.connect(on_stop);
+                reload_button.clicked.connect(on_reload);
+                restart_button.clicked.connect(on_restart);
 
                 bbox.pack_start(start_button, false, true, 0);
                 bbox.pack_start(stop_button, false, true, 0);
@@ -293,7 +293,7 @@ public class MainWindow : Window {
 
                 cancel_button = new Button.with_mnemonic("_Cancel");
 
-                cancel_button.clicked += on_cancel;
+                cancel_button.clicked.connect(on_cancel);
 
                 bbox.pack_start(cancel_button, false, true, 0);
 
@@ -304,10 +304,10 @@ public class MainWindow : Window {
                                 "/org/freedesktop/systemd1",
                                 "org.freedesktop.systemd1.Manager") as Manager;
 
-                manager.unit_new += on_unit_new;
-                manager.job_new += on_job_new;
-                manager.unit_removed += on_unit_removed;
-                manager.job_removed += on_job_removed;
+                manager.unit_new.connect(on_unit_new);
+                manager.job_new.connect(on_job_new);
+                manager.unit_removed.connect(on_unit_removed);
+                manager.job_removed.connect(on_job_removed);
 
                 manager.subscribe();
 
@@ -330,7 +330,7 @@ public class MainWindow : Window {
                                         i.unit_path,
                                         "org.freedesktop.systemd1.Unit") as Unit;
 
-                        u.changed += on_unit_changed;
+                        u.changed.connect(on_unit_changed);
 
                         unit_model.append(out iter);
                         unit_model.set(iter,
@@ -357,7 +357,7 @@ public class MainWindow : Window {
                                         i.job_path,
                                         "org.freedesktop.systemd1.Job") as Job;
 
-                        j.changed += on_job_changed;
+                        j.changed.connect(on_job_changed);
 
                         job_model.append(out iter);
                         job_model.set(iter,
@@ -677,7 +677,7 @@ public class MainWindow : Window {
                                 path,
                                 "org.freedesktop.systemd1.Unit") as Unit;
 
-                u.changed += on_unit_changed;
+                u.changed.connect(on_unit_changed);
 
                 TreeIter iter;
                 unit_model.append(out iter);
@@ -700,7 +700,7 @@ public class MainWindow : Window {
                                 path,
                                 "org.freedesktop.systemd1.Job") as Job;
 
-                j.changed += on_job_changed;
+                j.changed.connect(on_job_changed);
 
                 TreeIter iter;
                 job_model.append(out iter);
commit 7594fb250ba5f5a82a578065c5d9fe524ef706bb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 03:55:42 2010 +0200

    man: update systemctl man page

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 9f00324..80f3554 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -70,7 +70,7 @@
                 <variablelist>
                         <varlistentry>
                                 <term><option>--help</option></term>
-                                <term><option>--h</option></term>
+                                <term><option>-h</option></term>
 
                                 <listitem><para>Prints a short help
                                 text and exits.</para></listitem>
@@ -78,6 +78,7 @@
 
                         <varlistentry>
                                 <term><option>--type=</option></term>
+                                <term><option>-t</option></term>
 
                                 <listitem><para>When listing units,
                                 limit display to certain unit
@@ -91,6 +92,7 @@
 
                         <varlistentry>
                                 <term><option>--all</option></term>
+                                <term><option>-a</option></term>
 
                                 <listitem><para>When listing units,
                                 show all units, regardless of their
@@ -125,11 +127,25 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>--block</option></term>
+                                <term><option>--no-block</option></term>
 
-                                <listitem><para>Synchronously wait for
-                                the requested operation to
-                                finish.</para></listitem>
+                                <listitem><para>Do no synchronously
+                                wait for the requested operation to
+                                finish. If this is not specified the
+                                job will be verified, enqueued and
+                                wait until it is complete. By passing
+                                this argument it is only verified and
+                                enqueued.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--quiet</option></term>
+                                <term><option>-q</option></term>
+
+                                <listitem><para>Suppress output to
+                                STDOUT for <command>snapshot</command>
+                                and
+                                <command>check</command>.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -252,6 +268,18 @@
                                 others.</para></listitem>
                         </varlistentry>
                         <varlistentry>
+                                <term><command>check [NAME...]</command></term>
+
+                                <listitem><para>Check whether any of
+                                the specified units is active
+                                (i.e. running). Returns 0 if at least
+                                one is active, non-zero
+                                otherwise. Unless
+                                <option>--quiet</option> is specified
+                                this will also print the current unit
+                                state to STDOUT.</para></listitem>
+                        </varlistentry>
+                        <varlistentry>
                                 <term><command>monitor</command></term>
 
                                 <listitem><para>Monitor unit/job
@@ -280,8 +308,10 @@
                                 snapshot will be named after it. If
                                 none is specified an automatic
                                 snapshot name is generated. In either
-                                case, the snapshot name used is printed
-                                to STDOUT.</para>
+                                case, the snapshot name used is
+                                printed to STDOUT, unless
+                                <option>--quiet</option> is
+                                specified.</para>
 
                                 <para>A snapshot refers to a saved
                                 state of the systemd manager. It is
commit 5e374895934d6b8960e391a2b3a1fe57e153a7f8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 03:44:09 2010 +0200

    systemctl: return error codes for failed jobs

diff --git a/src/systemctl.c b/src/systemctl.c
index cf2871d..d6f4709 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -530,13 +530,18 @@ finish:
         return r;
 }
 
+typedef struct WaitData {
+        Set *set;
+        bool failed;
+} WaitData;
+
 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
         DBusError error;
-        Set *s = data;
+        WaitData *d = data;
 
         assert(connection);
         assert(message);
-        assert(s);
+        assert(d);
 
         dbus_error_init(&error);
 
@@ -552,17 +557,22 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
         } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
                 uint32_t id;
                 const char *path;
+                dbus_bool_t success = true;
 
                 if (!dbus_message_get_args(message, &error,
                                            DBUS_TYPE_UINT32, &id,
                                            DBUS_TYPE_OBJECT_PATH, &path,
+                                           DBUS_TYPE_BOOLEAN, &success,
                                            DBUS_TYPE_INVALID))
                         log_error("Failed to parse message: %s", error.message);
                 else {
                         char *p;
 
-                        if ((p = set_remove(s, (char*) path)))
+                        if ((p = set_remove(d->set, (char*) path)))
                                 free(p);
+
+                        if (!success)
+                                d->failed = true;
                 }
         }
 
@@ -627,11 +637,16 @@ finish:
 
 static int wait_for_jobs(DBusConnection *bus, Set *s) {
         int r;
+        WaitData d;
 
         assert(bus);
         assert(s);
 
-        if (!dbus_connection_add_filter(bus, wait_filter, s, NULL)) {
+        zero(d);
+        d.set = s;
+        d.failed = false;
+
+        if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
                 log_error("Failed to add filter.");
                 r = -ENOMEM;
                 goto finish;
@@ -641,7 +656,10 @@ static int wait_for_jobs(DBusConnection *bus, Set *s) {
                dbus_connection_read_write_dispatch(bus, -1))
                 ;
 
-        r = 0;
+        if (!arg_quiet && d.failed)
+                log_error("Job failed, see logs for details.");
+
+        r = d.failed ? -EIO : 0;
 
 finish:
         /* This is slightly dirty, since we don't undo the filter registration. */
commit 6ec1117a7416a999d588abf68a599b8bfd965ccd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 03:39:55 2010 +0200

    snapshot: ensure that snapshots cannot be created unless with create_snapshot

diff --git a/src/snapshot.c b/src/snapshot.c
index ea3894b..399aaea 100644
--- a/src/snapshot.c
+++ b/src/snapshot.c
@@ -47,6 +47,21 @@ static void snapshot_set_state(Snapshot *s, SnapshotState state) {
         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state]);
 }
 
+static int snapshot_load(Unit *u) {
+        Snapshot *s = SNAPSHOT(u);
+
+        assert(u);
+        assert(u->meta.load_state == UNIT_STUB);
+
+        /* Make sure that only snapshots created via snapshot_create()
+         * can be loaded */
+        if (!s->by_snapshot_create)
+                return -ENOENT;
+
+        u->meta.load_state = UNIT_LOADED;
+        return 0;
+}
+
 static int snapshot_coldplug(Unit *u) {
         Snapshot *s = SNAPSHOT(u);
 
@@ -197,12 +212,16 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, Snapshot **_s) {
                 name = n;
         }
 
-        r = manager_load_unit(m, name, NULL, &u);
+        r = manager_load_unit_prepare(m, name, NULL, &u);
         free(n);
 
         if (r < 0)
                 goto fail;
 
+        SNAPSHOT(u)->by_snapshot_create = true;
+        manager_dispatch_load_queue(m);
+        assert(u->meta.load_state == UNIT_LOADED);
+
         HASHMAP_FOREACH_KEY(other, k, m->units, i) {
 
                 if (UNIT_VTABLE(other)->no_snapshots)
@@ -258,7 +277,7 @@ const UnitVTable snapshot_vtable = {
         .no_snapshots = true,
         .no_gc = true,
 
-        .load = unit_load_nop,
+        .load = snapshot_load,
         .coldplug = snapshot_coldplug,
 
         .dump = snapshot_dump,
diff --git a/src/snapshot.h b/src/snapshot.h
index 959a509..2561790 100644
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -39,6 +39,7 @@ struct Snapshot {
         SnapshotState state, deserialized_state;
 
         bool cleanup;
+        bool by_snapshot_create:1;
 };
 
 extern const UnitVTable snapshot_vtable;
commit 032ff4afc953cae076ce0ee6a0b85020eeb1a75a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 03:34:15 2010 +0200

    unit: shorten active state enums to make systemctl output nicer

diff --git a/fixme b/fixme
index 09aba7d..2f0f929 100644
--- a/fixme
+++ b/fixme
@@ -35,16 +35,10 @@
 
 * selinux
 
-* systemctl check
-
-* nettere fehlermeldung bei systemctl start foo.service failure
-
-* systemd-install disable sollte den service runterfahren
+* systemd-install disable sollte den service runterfahren, and daemon-reload machen
 
 * systemctl daemon-reload is kaputt
 
-* keinerlei fehlermeldung bei dead symlink muss gefixt werden
-
 External:
 
 * patch /etc/init.d/functions with:
diff --git a/src/automount.c b/src/automount.c
index 84f2d97..5e669c5 100644
--- a/src/automount.c
+++ b/src/automount.c
@@ -40,7 +40,7 @@ static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
         [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
         [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
-        [AUTOMOUNT_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
+        [AUTOMOUNT_MAINTENANCE] = UNIT_MAINTENANCE
 };
 
 static int open_dev_autofs(Manager *m);
diff --git a/src/job.c b/src/job.c
index 8273a39..31e9cfe 100644
--- a/src/job.c
+++ b/src/job.c
@@ -275,26 +275,26 @@ bool job_type_is_redundant(JobType a, UnitActiveState b) {
         case JOB_START:
                 return
                         b == UNIT_ACTIVE ||
-                        b == UNIT_ACTIVE_RELOADING;
+                        b == UNIT_RELOADING;
 
         case JOB_STOP:
                 return
                         b == UNIT_INACTIVE ||
-                        b == UNIT_INACTIVE_MAINTENANCE;
+                        b == UNIT_MAINTENANCE;
 
         case JOB_VERIFY_ACTIVE:
                 return
                         b == UNIT_ACTIVE ||
-                        b == UNIT_ACTIVE_RELOADING;
+                        b == UNIT_RELOADING;
 
         case JOB_RELOAD:
                 return
-                        b == UNIT_ACTIVE_RELOADING;
+                        b == UNIT_RELOADING;
 
         case JOB_RELOAD_OR_START:
                 return
                         b == UNIT_ACTIVATING ||
-                        b == UNIT_ACTIVE_RELOADING;
+                        b == UNIT_RELOADING;
 
         case JOB_RESTART:
                 return
@@ -416,7 +416,7 @@ int job_run_and_invalidate(Job *j) {
 
                 case JOB_RESTART: {
                         UnitActiveState t = unit_active_state(j->unit);
-                        if (t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE || t == UNIT_ACTIVATING) {
+                        if (t == UNIT_INACTIVE || t == UNIT_MAINTENANCE || t == UNIT_ACTIVATING) {
                                 j->type = JOB_START;
                                 r = unit_start(j->unit);
                         } else
@@ -426,7 +426,7 @@ int job_run_and_invalidate(Job *j) {
 
                 case JOB_TRY_RESTART: {
                         UnitActiveState t = unit_active_state(j->unit);
-                        if (t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE || t == UNIT_DEACTIVATING)
+                        if (t == UNIT_INACTIVE || t == UNIT_MAINTENANCE || t == UNIT_DEACTIVATING)
                                 r = -ENOEXEC;
                         else if (t == UNIT_ACTIVATING) {
                                 j->type = JOB_START;
diff --git a/src/mount.c b/src/mount.c
index f033616..86c5b0a 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -42,15 +42,15 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_MOUNTING] = UNIT_ACTIVATING,
         [MOUNT_MOUNTING_DONE] = UNIT_ACTIVE,
         [MOUNT_MOUNTED] = UNIT_ACTIVE,
-        [MOUNT_REMOUNTING] = UNIT_ACTIVE_RELOADING,
+        [MOUNT_REMOUNTING] = UNIT_RELOADING,
         [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
         [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
         [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
-        [MOUNT_REMOUNTING_SIGTERM] = UNIT_ACTIVE_RELOADING,
-        [MOUNT_REMOUNTING_SIGKILL] = UNIT_ACTIVE_RELOADING,
+        [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
+        [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
         [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
         [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
-        [MOUNT_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
+        [MOUNT_MAINTENANCE] = UNIT_MAINTENANCE
 };
 
 static void mount_init(Unit *u) {
diff --git a/src/path.c b/src/path.c
index 16ea08d..80dc3c4 100644
--- a/src/path.c
+++ b/src/path.c
@@ -34,7 +34,7 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
         [PATH_DEAD] = UNIT_INACTIVE,
         [PATH_WAITING] = UNIT_ACTIVE,
         [PATH_RUNNING] = UNIT_ACTIVE,
-        [PATH_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
+        [PATH_MAINTENANCE] = UNIT_MAINTENANCE
 };
 
 static void path_done(Unit *u) {
diff --git a/src/service.c b/src/service.c
index 3102acc..d5e681a 100644
--- a/src/service.c
+++ b/src/service.c
@@ -76,14 +76,14 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
         [SERVICE_START_POST] = UNIT_ACTIVATING,
         [SERVICE_RUNNING] = UNIT_ACTIVE,
         [SERVICE_EXITED] = UNIT_ACTIVE,
-        [SERVICE_RELOAD] = UNIT_ACTIVE_RELOADING,
+        [SERVICE_RELOAD] = UNIT_RELOADING,
         [SERVICE_STOP] = UNIT_DEACTIVATING,
         [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
         [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
         [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
         [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
         [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
-        [SERVICE_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE,
+        [SERVICE_MAINTENANCE] = UNIT_MAINTENANCE,
         [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
 };
 
diff --git a/src/socket.c b/src/socket.c
index 83f8ebe..7e62dbc 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -50,7 +50,7 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
         [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
         [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
-        [SOCKET_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
+        [SOCKET_MAINTENANCE] = UNIT_MAINTENANCE
 };
 
 static void socket_init(Unit *u) {
diff --git a/src/swap.c b/src/swap.c
index e2afcc0..2e3e995 100644
--- a/src/swap.c
+++ b/src/swap.c
@@ -38,7 +38,7 @@
 static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
         [SWAP_DEAD] = UNIT_INACTIVE,
         [SWAP_ACTIVE] = UNIT_ACTIVE,
-        [SWAP_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
+        [SWAP_MAINTENANCE] = UNIT_MAINTENANCE
 };
 
 static void swap_init(Unit *u) {
diff --git a/src/timer.c b/src/timer.c
index 96c6e8e..f0005f5 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -31,7 +31,7 @@ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
         [TIMER_WAITING] = UNIT_ACTIVE,
         [TIMER_RUNNING] = UNIT_ACTIVE,
         [TIMER_ELAPSED] = UNIT_ACTIVE,
-        [TIMER_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
+        [TIMER_MAINTENANCE] = UNIT_MAINTENANCE
 };
 
 static void timer_init(Unit *u) {
diff --git a/src/unit.c b/src/unit.c
index 79b9e2b..9fed5a0 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -819,7 +819,7 @@ int unit_reload(Unit *u) {
                 return -EBADR;
 
         state = unit_active_state(u);
-        if (unit_active_state(u) == UNIT_ACTIVE_RELOADING)
+        if (unit_active_state(u) == UNIT_RELOADING)
                 return -EALREADY;
 
         if (unit_active_state(u) != UNIT_ACTIVE)
@@ -998,7 +998,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
                         if (u->meta.job->state == JOB_RUNNING) {
                                 if (ns == UNIT_ACTIVE)
                                         job_finish_and_invalidate(u->meta.job, true);
-                                else if (ns != UNIT_ACTIVATING && ns != UNIT_ACTIVE_RELOADING) {
+                                else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
                                         unexpected = true;
                                         job_finish_and_invalidate(u->meta.job, false);
                                 }
@@ -1012,7 +1012,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
 
                         if (ns == UNIT_INACTIVE)
                                 job_finish_and_invalidate(u->meta.job, true);
-                        else if (ns == UNIT_INACTIVE_MAINTENANCE)
+                        else if (ns == UNIT_MAINTENANCE)
                                 job_finish_and_invalidate(u->meta.job, false);
                         else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
                                 unexpected = true;
@@ -1964,9 +1964,9 @@ DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
 
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
-        [UNIT_ACTIVE_RELOADING] = "active-reloading",
+        [UNIT_RELOADING] = "reloading",
         [UNIT_INACTIVE] = "inactive",
-        [UNIT_INACTIVE_MAINTENANCE] = "inactive-maintenance",
+        [UNIT_MAINTENANCE] = "maintenance",
         [UNIT_ACTIVATING] = "activating",
         [UNIT_DEACTIVATING] = "deactivating"
 };
diff --git a/src/unit.h b/src/unit.h
index 0303189..aa80aad 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -78,9 +78,9 @@ enum UnitLoadState {
 
 enum UnitActiveState {
         UNIT_ACTIVE,
-        UNIT_ACTIVE_RELOADING,
+        UNIT_RELOADING,
         UNIT_INACTIVE,
-        UNIT_INACTIVE_MAINTENANCE,
+        UNIT_MAINTENANCE,
         UNIT_ACTIVATING,
         UNIT_DEACTIVATING,
         _UNIT_ACTIVE_STATE_MAX,
@@ -88,19 +88,19 @@ enum UnitActiveState {
 };
 
 static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
-        return t == UNIT_ACTIVE || t == UNIT_ACTIVE_RELOADING;
+        return t == UNIT_ACTIVE || t == UNIT_RELOADING;
 }
 
 static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) {
-        return t == UNIT_ACTIVE || t == UNIT_ACTIVATING || t == UNIT_ACTIVE_RELOADING;
+        return t == UNIT_ACTIVE || t == UNIT_ACTIVATING || t == UNIT_RELOADING;
 }
 
 static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) {
-        return t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE || t == UNIT_DEACTIVATING;
+        return t == UNIT_INACTIVE || t == UNIT_MAINTENANCE || t == UNIT_DEACTIVATING;
 }
 
 static inline bool UNIT_IS_INACTIVE_OR_MAINTENANCE(UnitActiveState t) {
-        return t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE;
+        return t == UNIT_INACTIVE || t == UNIT_MAINTENANCE;
 }
 
 enum UnitDependency {
commit 2419cc5bdb66304adf7be4cf60af91979c5d24d9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 01:07:13 2010 +0200

    socket: fix D-Bus introspection data

diff --git a/src/dbus-socket.c b/src/dbus-socket.c
index 3ba26cc..cadb904 100644
--- a/src/dbus-socket.c
+++ b/src/dbus-socket.c
@@ -39,13 +39,13 @@
         "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
         "  <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
-        "  <priority name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
-        "  <priority name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
-        "  <priority name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
-        "  <priority name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
-        "  <priority name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
-        "  <priority name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
-        "  <priority name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
+        "  <property name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
+        "  <property name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
+        "  <property name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
+        "  <property name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
+        "  <property name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
         " </interface>\n"                                               \
 
 #define INTROSPECTION                                                   \
commit 0183528f6b9bb444e65f46d1c8fccd1303723d02
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 01:06:58 2010 +0200

    systemctl: add 'check' call

diff --git a/src/systemctl.c b/src/systemctl.c
index 15e5ecf..cf2871d 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -52,6 +52,7 @@ static bool arg_no_wtmp = false;
 static bool arg_no_sync = false;
 static bool arg_no_wall = false;
 static bool arg_dry = false;
+static bool arg_quiet = false;
 static char **arg_wall = NULL;
 enum action {
         ACTION_INVALID,
@@ -849,6 +850,128 @@ static int start_special(DBusConnection *bus, char **args, unsigned n) {
         return start_unit(bus, args, n);
 }
 
+static int check_unit(DBusConnection *bus, char **args, unsigned n) {
+        DBusMessage *m = NULL, *reply = NULL;
+        const char
+                *interface = "org.freedesktop.systemd1.Unit",
+                *property = "ActiveState";
+        int r = -EADDRNOTAVAIL;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 1; i < n; i++) {
+                const char *path = NULL;
+                const char *state;
+                DBusMessageIter iter, sub;
+
+                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, &args[i],
+                                              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, cannot figure out anything about this unit... */
+                        if (!arg_quiet)
+                                puts("unknown");
+
+                        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);
+
+                if (!arg_quiet)
+                        puts(state);
+
+                if (streq(state, "active") || startswith(state, "active-"))
+                        r = 0;
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return r;
+
+}
+
 static DBusHandlerResult monitor_filter(DBusConnection *connection, DBusMessage *message, void *data) {
         DBusError error;
         DBusMessage *m = NULL, *reply = NULL;
@@ -1205,7 +1328,9 @@ static int snapshot(DBusConnection *bus, char **args, unsigned n) {
         }
 
         dbus_message_iter_get_basic(&sub, &id);
-        puts(id);
+
+        if (!arg_quiet)
+                puts(id);
         r = 0;
 
 finish:
@@ -1436,6 +1561,7 @@ static int systemctl_help(void) {
                "     --replace   When installing a new job, replace existing conflicting ones\n"
                "     --system    Connect to system bus\n"
                "     --session   Connect to session bus\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"
                "Commands:\n"
@@ -1449,6 +1575,7 @@ static int systemctl_help(void) {
                "  restart [NAME...]               Restart one or more units\n"
                "  reload [NAME...]                Reload one or more units\n"
                "  isolate [NAME]                  Start one unit and stop all others\n"
+               "  check [NAME...]                 Check whether any of the passed units are active\n"
                "  monitor                         Monitor unit/job changes\n"
                "  dump                            Dump server status\n"
                "  snapshot [NAME]                 Create a snapshot\n"
@@ -1553,6 +1680,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "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'          },
                 { NULL,        0,                 NULL, 0            }
         };
 
@@ -1561,7 +1689,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hta", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "htaq", options, NULL)) >= 0) {
 
                 switch (c) {
 
@@ -1597,6 +1725,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_no_wall = true;
                         break;
 
+                case 'q':
+                        arg_quiet = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -2108,6 +2240,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
                 { "reload",            MORE,  2, start_unit      },
                 { "restart",           MORE,  2, start_unit      },
                 { "isolate",           EQUAL, 2, start_unit      },
+                { "check",             MORE,  2, check_unit      },
                 { "monitor",           EQUAL, 1, monitor         },
                 { "dump",              EQUAL, 1, dump            },
                 { "snapshot",          LESS,  2, snapshot        },
@@ -2138,6 +2271,11 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
                 /* Special rule: no arguments means "list-units" */
                 i = 0;
         else {
+                if (streq(argv[optind], "help")) {
+                        systemctl_help();
+                        return 0;
+                }
+
                 for (i = 0; i < ELEMENTSOF(verbs); i++)
                         if (streq(argv[optind], verbs[i].verb))
                                 break;
commit 6e905d936021a31fe118e3806aec7db5bc34c77a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 00:32:29 2010 +0200

    systemctl: block by default

diff --git a/src/systemctl.c b/src/systemctl.c
index 78310aa..15e5ecf 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -46,7 +46,7 @@ static const char *arg_type = NULL;
 static bool arg_all = false;
 static bool arg_replace = false;
 static bool arg_session = false;
-static bool arg_block = false;
+static bool arg_no_block = false;
 static bool arg_immediate = false;
 static bool arg_no_wtmp = false;
 static bool arg_no_sync = false;
@@ -663,7 +663,7 @@ static int start_unit_one(
         assert(method);
         assert(name);
         assert(mode);
-        assert(!arg_block || s);
+        assert(arg_no_block || s);
 
         dbus_error_init(&error);
 
@@ -700,7 +700,7 @@ static int start_unit_one(
                 goto finish;
         }
 
-        if (arg_block) {
+        if (!arg_no_block) {
                 const char *path;
                 char *p;
 
@@ -806,7 +806,7 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
                 one_name = table[arg_action];
         }
 
-        if (arg_block) {
+        if (!arg_no_block) {
                 if ((r = enable_wait_for_jobs(bus)) < 0) {
                         log_error("Could not watch jobs: %s", strerror(-r));
                         goto finish;
@@ -830,7 +830,7 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
                                 goto finish;
         }
 
-        if (arg_block)
+        if (!arg_no_block)
                 r = wait_for_jobs(bus, s);
 
 finish:
@@ -1436,7 +1436,7 @@ static int systemctl_help(void) {
                "     --replace   When installing a new job, replace existing conflicting ones\n"
                "     --system    Connect to system bus\n"
                "     --session   Connect to session bus\n"
-               "     --block     Wait until operation finished\n"
+               "     --no-block  Do not wait until operation finished\n"
                "     --no-wall   Don't send wall message before halt/power-off/reboot\n\n"
                "Commands:\n"
                "  list-units                      List units\n"
@@ -1540,20 +1540,20 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_REPLACE = 0x100,
                 ARG_SESSION,
                 ARG_SYSTEM,
-                ARG_BLOCK,
+                ARG_NO_BLOCK,
                 ARG_NO_WALL
         };
 
         static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'         },
-                { "type",      required_argument, NULL, 't'         },
-                { "all",       no_argument,       NULL, 'a'         },
-                { "replace",   no_argument,       NULL, ARG_REPLACE },
-                { "session",   no_argument,       NULL, ARG_SESSION },
-                { "system",    no_argument,       NULL, ARG_SYSTEM  },
-                { "block",     no_argument,       NULL, ARG_BLOCK   },
-                { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
-                { NULL,        0,                 NULL, 0           }
+                { "help",      no_argument,       NULL, 'h'          },
+                { "type",      required_argument, NULL, 't'          },
+                { "all",       no_argument,       NULL, 'a'          },
+                { "replace",   no_argument,       NULL, ARG_REPLACE  },
+                { "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  },
+                { NULL,        0,                 NULL, 0            }
         };
 
         int c;
@@ -1589,8 +1589,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_session = false;
                         break;
 
-                case ARG_BLOCK:
-                        arg_block = true;
+                case ARG_NO_BLOCK:
+                        arg_no_block = true;
                         break;
 
                 case ARG_NO_WALL:
commit 6124958c7bda3fed9b079e8217781480797703f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 00:31:53 2010 +0200

    unit: add new abstracted maintenance state for units

diff --git a/fixme b/fixme
index 3ca6a02..09aba7d 100644
--- a/fixme
+++ b/fixme
@@ -10,8 +10,6 @@
 
 * "disabled" load state?
 
-* gc: don't reap broken services
-
 * ability to kill services? i.e. in contrast to stopping them, go directly
   into killing mode?
 
@@ -37,9 +35,17 @@
 
 * selinux
 
-External:
+* systemctl check
+
+* nettere fehlermeldung bei systemctl start foo.service failure
+
+* systemd-install disable sollte den service runterfahren
 
-* systemd-sysvinit as package
+* systemctl daemon-reload is kaputt
+
+* keinerlei fehlermeldung bei dead symlink muss gefixt werden
+
+External:
 
 * patch /etc/init.d/functions with:
 
diff --git a/src/automount.c b/src/automount.c
index 75c1053..84f2d97 100644
--- a/src/automount.c
+++ b/src/automount.c
@@ -40,7 +40,7 @@ static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
         [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
         [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
-        [AUTOMOUNT_MAINTENANCE] = UNIT_INACTIVE,
+        [AUTOMOUNT_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static int open_dev_autofs(Manager *m);
diff --git a/src/job.c b/src/job.c
index 78fe136..8273a39 100644
--- a/src/job.c
+++ b/src/job.c
@@ -279,7 +279,8 @@ bool job_type_is_redundant(JobType a, UnitActiveState b) {
 
         case JOB_STOP:
                 return
-                        b == UNIT_INACTIVE;
+                        b == UNIT_INACTIVE ||
+                        b == UNIT_INACTIVE_MAINTENANCE;
 
         case JOB_VERIFY_ACTIVE:
                 return
@@ -415,7 +416,7 @@ int job_run_and_invalidate(Job *j) {
 
                 case JOB_RESTART: {
                         UnitActiveState t = unit_active_state(j->unit);
-                        if (t == UNIT_INACTIVE || t == UNIT_ACTIVATING) {
+                        if (t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE || t == UNIT_ACTIVATING) {
                                 j->type = JOB_START;
                                 r = unit_start(j->unit);
                         } else
@@ -425,7 +426,7 @@ int job_run_and_invalidate(Job *j) {
 
                 case JOB_TRY_RESTART: {
                         UnitActiveState t = unit_active_state(j->unit);
-                        if (t == UNIT_INACTIVE || t == UNIT_DEACTIVATING)
+                        if (t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE || t == UNIT_DEACTIVATING)
                                 r = -ENOEXEC;
                         else if (t == UNIT_ACTIVATING) {
                                 j->type = JOB_START;
diff --git a/src/manager.c b/src/manager.c
index b8daffd..74a414a 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -1343,7 +1343,7 @@ static int transaction_add_isolate_jobs(Manager *m) {
                         continue;
 
                 /* No need to stop inactive jobs */
-                if (unit_active_state(u) == UNIT_INACTIVE)
+                if (UNIT_IS_INACTIVE_OR_MAINTENANCE(unit_active_state(u)))
                         continue;
 
                 /* Is there already something listed for this? */
diff --git a/src/mount.c b/src/mount.c
index 081e92c..f033616 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -50,7 +50,7 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_REMOUNTING_SIGKILL] = UNIT_ACTIVE_RELOADING,
         [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
         [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
-        [MOUNT_MAINTENANCE] = UNIT_INACTIVE,
+        [MOUNT_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static void mount_init(Unit *u) {
diff --git a/src/path.c b/src/path.c
index 24545ba..16ea08d 100644
--- a/src/path.c
+++ b/src/path.c
@@ -34,7 +34,7 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
         [PATH_DEAD] = UNIT_INACTIVE,
         [PATH_WAITING] = UNIT_ACTIVE,
         [PATH_RUNNING] = UNIT_ACTIVE,
-        [PATH_MAINTENANCE] = UNIT_INACTIVE
+        [PATH_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static void path_done(Unit *u) {
diff --git a/src/service.c b/src/service.c
index e1dab70..3102acc 100644
--- a/src/service.c
+++ b/src/service.c
@@ -83,8 +83,8 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
         [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
         [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
         [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
-        [SERVICE_MAINTENANCE] = UNIT_INACTIVE,
-        [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
+        [SERVICE_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE,
+        [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
 };
 
 static void service_init(Unit *u) {
diff --git a/src/socket.c b/src/socket.c
index f20b78d..83f8ebe 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -50,7 +50,7 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
         [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
         [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
-        [SOCKET_MAINTENANCE] = UNIT_INACTIVE,
+        [SOCKET_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static void socket_init(Unit *u) {
diff --git a/src/swap.c b/src/swap.c
index 663c568..e2afcc0 100644
--- a/src/swap.c
+++ b/src/swap.c
@@ -38,7 +38,7 @@
 static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
         [SWAP_DEAD] = UNIT_INACTIVE,
         [SWAP_ACTIVE] = UNIT_ACTIVE,
-        [SWAP_MAINTENANCE] = UNIT_INACTIVE
+        [SWAP_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static void swap_init(Unit *u) {
diff --git a/src/timer.c b/src/timer.c
index ead8ab9..96c6e8e 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -31,7 +31,7 @@ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
         [TIMER_WAITING] = UNIT_ACTIVE,
         [TIMER_RUNNING] = UNIT_ACTIVE,
         [TIMER_ELAPSED] = UNIT_ACTIVE,
-        [TIMER_MAINTENANCE] = UNIT_INACTIVE
+        [TIMER_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static void timer_init(Unit *u) {
@@ -401,7 +401,7 @@ void timer_unit_notify(Unit *u, UnitActiveState new_state) {
 
                 case TIMER_RUNNING:
 
-                        if (new_state == UNIT_INACTIVE) {
+                        if (UNIT_IS_INACTIVE_OR_MAINTENANCE(new_state)) {
                                 log_debug("%s got notified about unit deactivation.", t->meta.id);
                                 timer_enter_waiting(t, false);
                         }
diff --git a/src/unit.c b/src/unit.c
index 76e8cd7..79b9e2b 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -365,8 +365,12 @@ void unit_free(Unit *u) {
 UnitActiveState unit_active_state(Unit *u) {
         assert(u);
 
-        if (u->meta.load_state != UNIT_LOADED)
-                return UNIT_INACTIVE;
+        if (u->meta.load_state == UNIT_MERGED)
+                return unit_active_state(unit_follow_merge(u));
+
+        /* After a reload it might happen that a unit is not correctly
+         * loaded but still has a process around. That's why we won't
+         * shortcut failed loading to UNIT_INACTIVE_MAINTENANCE. */
 
         return UNIT_VTABLE(u)->active_state(u);
 }
@@ -463,7 +467,7 @@ int unit_merge(Unit *u, Unit *other) {
         if (other->meta.job)
                 return -EEXIST;
 
-        if (unit_active_state(other) != UNIT_INACTIVE)
+        if (!UNIT_IS_INACTIVE_OR_MAINTENANCE(unit_active_state(other)))
                 return -EEXIST;
 
         /* Merge names */
@@ -746,6 +750,9 @@ int unit_start(Unit *u) {
 
         assert(u);
 
+        if (u->meta.load_state != UNIT_LOADED)
+                return -EINVAL;
+
         /* If this is already (being) started, then this will
          * succeed. Note that this will even succeed if this unit is
          * not startable by the user. This is relied on to detect when
@@ -785,7 +792,7 @@ int unit_stop(Unit *u) {
         assert(u);
 
         state = unit_active_state(u);
-        if (state == UNIT_INACTIVE)
+        if (UNIT_IS_INACTIVE_OR_MAINTENANCE(state))
                 return -EALREADY;
 
         if (!UNIT_VTABLE(u)->stop)
@@ -805,6 +812,9 @@ int unit_reload(Unit *u) {
 
         assert(u);
 
+        if (u->meta.load_state != UNIT_LOADED)
+                return -EINVAL;
+
         if (!unit_can_reload(u))
                 return -EBADR;
 
@@ -941,9 +951,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
 
         dual_timestamp_get(&ts);
 
-        if (os == UNIT_INACTIVE && ns != UNIT_INACTIVE)
+        if (UNIT_IS_INACTIVE_OR_MAINTENANCE(os) && !UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
                 u->meta.inactive_exit_timestamp = ts;
-        else if (os != UNIT_INACTIVE && ns == UNIT_INACTIVE)
+        else if (!UNIT_IS_INACTIVE_OR_MAINTENANCE(os) && UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
                 u->meta.inactive_enter_timestamp = ts;
 
         if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
@@ -1002,6 +1012,8 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
 
                         if (ns == UNIT_INACTIVE)
                                 job_finish_and_invalidate(u->meta.job, true);
+                        else if (ns == UNIT_INACTIVE_MAINTENANCE)
+                                job_finish_and_invalidate(u->meta.job, false);
                         else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
                                 unexpected = true;
                                 job_finish_and_invalidate(u->meta.job, false);
@@ -1952,7 +1964,9 @@ DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
 
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
+        [UNIT_ACTIVE_RELOADING] = "active-reloading",
         [UNIT_INACTIVE] = "inactive",
+        [UNIT_INACTIVE_MAINTENANCE] = "inactive-maintenance",
         [UNIT_ACTIVATING] = "activating",
         [UNIT_DEACTIVATING] = "deactivating"
 };
diff --git a/src/unit.h b/src/unit.h
index 70b3c9a..0303189 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -80,6 +80,7 @@ enum UnitActiveState {
         UNIT_ACTIVE,
         UNIT_ACTIVE_RELOADING,
         UNIT_INACTIVE,
+        UNIT_INACTIVE_MAINTENANCE,
         UNIT_ACTIVATING,
         UNIT_DEACTIVATING,
         _UNIT_ACTIVE_STATE_MAX,
@@ -95,7 +96,11 @@ static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) {
 }
 
 static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) {
-        return t == UNIT_INACTIVE || t == UNIT_DEACTIVATING;
+        return t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE || t == UNIT_DEACTIVATING;
+}
+
+static inline bool UNIT_IS_INACTIVE_OR_MAINTENANCE(UnitActiveState t) {
+        return t == UNIT_INACTIVE || t == UNIT_INACTIVE_MAINTENANCE;
 }
 
 enum UnitDependency {
commit 4fd5948e74b776b6d68ba55f558da5f354179e52
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 00:29:17 2010 +0200

    socket: make various socket/pipe options configurable

diff --git a/src/dbus-socket.c b/src/dbus-socket.c
index a5474c9..3ba26cc 100644
--- a/src/dbus-socket.c
+++ b/src/dbus-socket.c
@@ -37,6 +37,15 @@
         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
+        "  <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
+        "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
+        "  <priority name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
+        "  <priority name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
+        "  <priority name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
+        "  <priority name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
+        "  <priority name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
+        "  <priority name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
+        "  <priority name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
         " </interface>\n"                                               \
 
 #define INTROSPECTION                                                   \
@@ -66,6 +75,15 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMes
                 { "org.freedesktop.systemd1.Socket", "DirectoryMode", bus_property_append_mode,     "u", &u->socket.directory_mode },
                 { "org.freedesktop.systemd1.Socket", "SocketMode",    bus_property_append_mode,     "u", &u->socket.socket_mode },
                 { "org.freedesktop.systemd1.Socket", "Accept",        bus_property_append_bool,     "b", &u->socket.accept },
+                { "org.freedesktop.systemd1.Socket", "KeepAlive",     bus_property_append_bool,     "b", &u->socket.keep_alive },
+                { "org.freedesktop.systemd1.Socket", "Priority",      bus_property_append_int,      "i", &u->socket.priority },
+                { "org.freedesktop.systemd1.Socket", "ReceiveBuffer", bus_property_append_size,     "t", &u->socket.receive_buffer },
+                { "org.freedesktop.systemd1.Socket", "SendBuffer",    bus_property_append_size,     "t", &u->socket.send_buffer },
+                { "org.freedesktop.systemd1.Socket", "IPTOS",         bus_property_append_int,      "i", &u->socket.ip_tos },
+                { "org.freedesktop.systemd1.Socket", "IPTTL",         bus_property_append_int,      "i", &u->socket.ip_ttl },
+                { "org.freedesktop.systemd1.Socket", "PipeSize",      bus_property_append_size,     "t", &u->socket.pipe_size },
+                { "org.freedesktop.systemd1.Socket", "FreeBind",      bus_property_append_bool,     "b", &u->socket.free_bind },
+                { "org.freedesktop.systemd1.Socket", "Mark",          bus_property_append_int,      "i", &u->socket.mark },
                 { NULL, NULL, NULL, NULL, NULL }
         };
 
diff --git a/src/dbus.c b/src/dbus.c
index 74b1c37..2c2a9cd 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -1460,6 +1460,22 @@ int bus_property_append_int32(Manager *m, DBusMessageIter *i, const char *proper
         return 0;
 }
 
+int bus_property_append_size(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        uint64_t u;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(data);
+
+        u = (uint64_t) *(size_t*) data;
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+                return -ENOMEM;
+
+        return 0;
+}
+
 int bus_parse_strv(DBusMessage *m, char ***_l) {
         DBusMessageIter iter, sub;
         unsigned n = 0, i = 0;
diff --git a/src/dbus.h b/src/dbus.h
index af837f2..91132fd 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -77,6 +77,7 @@ int bus_property_append_bool(Manager *m, DBusMessageIter *i, const char *propert
 int bus_property_append_int32(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_property_append_uint32(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_property_append_uint64(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_size(Manager *m, DBusMessageIter *i, const char *property, void *data);
 
 #define bus_property_append_int bus_property_append_int32
 #define bus_property_append_pid bus_property_append_uint32
diff --git a/src/load-fragment.c b/src/load-fragment.c
index b7bb4d7..12f7617 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -1205,6 +1205,33 @@ finish:
         return r;
 }
 
+static int config_parse_ip_tos(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        int *ip_tos = data, x;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if ((x = ip_tos_from_string(rvalue)) < 0)
+                if ((r = safe_atoi(rvalue, &x)) < 0) {
+                        log_error("[%s:%u] Failed to parse IP TOS value: %s", filename, line, rvalue);
+                        return r;
+                }
+
+        *ip_tos = x;
+        return 0;
+}
+
 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
 
 #define FOLLOW_MAX 8
@@ -1517,6 +1544,15 @@ static int load_from_path(Unit *u, const char *path) {
                 { "KillMode",               config_parse_kill_mode,       &u->socket.kill_mode,                            "Socket"  },
                 { "Accept",                 config_parse_bool,            &u->socket.accept,                               "Socket"  },
                 { "MaxConnections",         config_parse_unsigned,        &u->socket.max_connections,                      "Socket"  },
+                { "KeepAlive",              config_parse_bool,            &u->socket.keep_alive,                           "Socket"  },
+                { "Priority",               config_parse_int,             &u->socket.priority,                             "Socket"  },
+                { "ReceiveBuffer",          config_parse_size,            &u->socket.receive_buffer,                       "Socket"  },
+                { "SendBuffer",             config_parse_size,            &u->socket.send_buffer,                          "Socket"  },
+                { "IPTOS",                  config_parse_ip_tos,          &u->socket.ip_tos,                               "Socket"  },
+                { "IPTTL",                  config_parse_int,             &u->socket.ip_ttl,                               "Socket"  },
+                { "Mark",                   config_parse_int,             &u->socket.mark,                                 "Socket"  },
+                { "PipeSize",               config_parse_size,            &u->socket.pipe_size,                            "Socket"  },
+                { "FreeBind",               config_parse_bool,            &u->socket.free_bind,                            "Socket"  },
                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
 
                 { "What",                   config_parse_string,          &u->mount.parameters_fragment.what,              "Mount"   },
diff --git a/src/missing.h b/src/missing.h
index 7db7d7d..75bc511 100644
--- a/src/missing.h
+++ b/src/missing.h
@@ -31,6 +31,18 @@
 #define RLIMIT_RTTIME 15
 #endif
 
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_SETPIPE_SZ
+#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
+#endif
+
+#ifndef F_GETPIPE_SZ
+#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
+#endif
+
 static inline int pivot_root(const char *new_root, const char *put_old) {
         return syscall(SYS_pivot_root, new_root, put_old);
 }
diff --git a/src/socket-util.c b/src/socket-util.c
index 4a1b3d8..344d6b9 100644
--- a/src/socket-util.c
+++ b/src/socket-util.c
@@ -305,6 +305,7 @@ int socket_address_listen(
                 int backlog,
                 SocketAddressBindIPv6Only only,
                 const char *bind_to_device,
+                bool free_bind,
                 mode_t directory_mode,
                 mode_t socket_mode,
                 int *ret) {
@@ -330,6 +331,12 @@ int socket_address_listen(
                 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
                         goto fail;
 
+        if (free_bind) {
+                one = 1;
+                if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
+                        log_warning("IP_FREEBIND failed: %m");
+        }
+
         one = 1;
         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
                 goto fail;
diff --git a/src/socket-util.h b/src/socket-util.h
index ffcc868..ae311ea 100644
--- a/src/socket-util.h
+++ b/src/socket-util.h
@@ -68,6 +68,7 @@ int socket_address_listen(
                 int backlog,
                 SocketAddressBindIPv6Only only,
                 const char *bind_to_device,
+                bool free_bind,
                 mode_t directory_mode,
                 mode_t socket_mode,
                 int *ret);
diff --git a/src/socket.c b/src/socket.c
index 7a8624c..f20b78d 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -36,6 +36,7 @@
 #include "strv.h"
 #include "unit-name.h"
 #include "dbus-socket.h"
+#include "missing.h"
 
 static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = UNIT_INACTIVE,
@@ -65,6 +66,16 @@ static void socket_init(Unit *u) {
 
         s->max_connections = 64;
 
+        s->keep_alive = false;
+        s->priority = -1;
+        s->receive_buffer = 0;
+        s->send_buffer = 0;
+        s->ip_tos = -1;
+        s->ip_ttl = -1;
+        s->pipe_size = 0;
+        s->mark = -1;
+        s->free_bind = false;
+
         exec_context_init(&s->exec_context);
 
         s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
@@ -308,13 +319,17 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sBacklog: %u\n"
                 "%sKillMode: %s\n"
                 "%sSocketMode: %04o\n"
-                "%sDirectoryMode: %04o\n",
+                "%sDirectoryMode: %04o\n"
+                "%sKeepAlive: %s\n"
+                "%sFreeBind: %s\n",
                 prefix, socket_state_to_string(s->state),
                 prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
                 prefix, s->backlog,
                 prefix, kill_mode_to_string(s->kill_mode),
                 prefix, s->socket_mode,
-                prefix, s->directory_mode);
+                prefix, s->directory_mode,
+                prefix, yes_no(s->keep_alive),
+                prefix, yes_no(s->free_bind));
 
         if (s->control_pid > 0)
                 fprintf(f,
@@ -335,6 +350,41 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         prefix, s->n_connections,
                         prefix, s->max_connections);
 
+        if (s->priority >= 0)
+                fprintf(f,
+                        "%sPriority: %i\n",
+                        prefix, s->priority);
+
+        if (s->receive_buffer > 0)
+                fprintf(f,
+                        "%sReceiveBuffer: %zu\n",
+                        prefix, s->receive_buffer);
+
+        if (s->send_buffer > 0)
+                fprintf(f,
+                        "%sSendBuffer: %zu\n",
+                        prefix, s->send_buffer);
+
+        if (s->ip_tos >= 0)
+                fprintf(f,
+                        "%sIPTOS: %i\n",
+                        prefix, s->ip_tos);
+
+        if (s->ip_ttl >= 0)
+                fprintf(f,
+                        "%sIPTTL: %i\n",
+                        prefix, s->ip_ttl);
+
+        if (s->pipe_size > 0)
+                fprintf(f,
+                        "%sPipeSize: %zu\n",
+                        prefix, s->pipe_size);
+
+        if (s->mark >= 0)
+                fprintf(f,
+                        "%sMark: %i\n",
+                        prefix, s->mark);
+
         LIST_FOREACH(port, p, s->ports) {
 
                 if (p->type == SOCKET_SOCKET) {
@@ -493,6 +543,54 @@ static void socket_close_fds(Socket *s) {
         }
 }
 
+static void socket_apply_socket_options(Socket *s, int fd) {
+        assert(s);
+        assert(fd >= 0);
+
+        if (s->keep_alive) {
+                int b = s->keep_alive;
+                if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &b, sizeof(b)) < 0)
+                        log_warning("SO_KEEPALIVE failed: %m");
+        }
+
+        if (s->priority >= 0)
+                if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &s->priority, sizeof(s->priority)) < 0)
+                        log_warning("SO_PRIORITY failed: %m");
+
+        if (s->receive_buffer > 0) {
+                int value = (int) s->receive_buffer;
+                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
+                        log_warning("SO_RCVBUF failed: %m");
+        }
+
+        if (s->send_buffer > 0) {
+                int value = (int) s->send_buffer;
+                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
+                        log_warning("SO_SNDBUF failed: %m");
+        }
+
+        if (s->mark >= 0)
+                if (setsockopt(fd, SOL_SOCKET, SO_MARK, &s->mark, sizeof(s->mark)) < 0)
+                        log_warning("SO_MARK failed: %m");
+
+        if (s->ip_tos >= 0)
+                if (setsockopt(fd, IPPROTO_IP, IP_TOS, &s->ip_tos, sizeof(s->ip_tos)) < 0)
+                        log_warning("IP_TOS failed: %m");
+
+        if (s->ip_ttl >= 0)
+                if (setsockopt(fd, IPPROTO_IP, IP_TTL, &s->ip_ttl, sizeof(s->ip_ttl)) < 0)
+                        log_warning("IP_TTL failed: %m");
+}
+
+static void socket_apply_pipe_options(Socket *s, int fd) {
+        assert(s);
+        assert(fd >= 0);
+
+        if (s->pipe_size > 0)
+                if (fcntl(fd, F_SETPIPE_SZ, s->pipe_size) < 0)
+                        log_warning("F_SETPIPE_SZ: %m");
+}
+
 static int socket_open_fds(Socket *s) {
         SocketPort *p;
         int r;
@@ -511,11 +609,14 @@ static int socket_open_fds(Socket *s) {
                                              s->backlog,
                                              s->bind_ipv6_only,
                                              s->bind_to_device,
+                                             s->free_bind,
                                              s->directory_mode,
                                              s->socket_mode,
                                              &p->fd)) < 0)
                                 goto rollback;
 
+                        socket_apply_socket_options(s, p->fd);
+
                 } else {
                         struct stat st;
                         assert(p->type == SOCKET_FIFO);
@@ -543,6 +644,8 @@ static int socket_open_fds(Socket *s) {
                                 r = -EEXIST;
                                 goto rollback;
                         }
+
+                        socket_apply_pipe_options(s, p->fd);
                 }
         }
 
@@ -1253,6 +1356,8 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
 
                         break;
                 }
+
+                socket_apply_socket_options(s, cfd);
         }
 
         socket_enter_running(s, cfd);
diff --git a/src/socket.h b/src/socket.h
index 31b3870..0674cd8 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -78,10 +78,7 @@ struct Socket {
 
         LIST_HEAD(SocketPort, ports);
 
-        /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
-        SocketAddressBindIPv6Only bind_ipv6_only;
         unsigned backlog;
-
         usec_t timeout_usec;
 
         ExecCommand* exec_command[_SOCKET_EXEC_COMMAND_MAX];
@@ -97,10 +94,6 @@ struct Socket {
         SocketExecCommand control_command_id;
         pid_t control_pid;
 
-        char *bind_to_device;
-        mode_t directory_mode;
-        mode_t socket_mode;
-
         bool accept;
         unsigned n_accepted;
         unsigned n_connections;
@@ -108,6 +101,24 @@ struct Socket {
 
         bool failure;
         Watch timer_watch;
+
+        /* Socket options */
+        bool keep_alive;
+        int priority;
+        size_t receive_buffer;
+        size_t send_buffer;
+        int ip_tos;
+        int ip_ttl;
+        size_t pipe_size;
+        int mark;
+        bool free_bind;
+        char *bind_to_device;
+
+        /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
+        SocketAddressBindIPv6Only bind_ipv6_only;
+
+        mode_t directory_mode;
+        mode_t socket_mode;
 };
 
 /* Called from the service code when collecting fds */
diff --git a/src/util.c b/src/util.c
index 41d8e7f..b66eb46 100644
--- a/src/util.c
+++ b/src/util.c
@@ -46,6 +46,7 @@
 #include <sys/prctl.h>
 #include <sys/utsname.h>
 #include <pwd.h>
+#include <netinet/ip.h>
 
 #include "macro.h"
 #include "util.h"
@@ -2625,3 +2626,12 @@ static const char* const rlimit_table[] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
+
+static const char* const ip_tos_table[] = {
+        [IPTOS_LOWDELAY] = "low-delay",
+        [IPTOS_THROUGHPUT] = "throughput",
+        [IPTOS_RELIABILITY] = "reliability",
+        [IPTOS_LOWCOST] = "low-cost",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
diff --git a/src/util.h b/src/util.h
index 91e0359..eda8e5c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -226,7 +226,8 @@ unsigned long long random_ull(void);
                 unsigned u = 0;                                         \
                 assert(s);                                              \
                 for (i = 0; i < (type)ELEMENTSOF(name##_table); i++)    \
-                        if (streq(name##_table[i], s))                  \
+                        if (name##_table[i] &&                          \
+                            streq(name##_table[i], s))                  \
                                 return i;                               \
                 if (safe_atou(s, &u) >= 0 &&                            \
                     u < ELEMENTSOF(name##_table))                       \
@@ -301,4 +302,7 @@ int sched_policy_from_string(const char *s);
 const char *rlimit_to_string(int i);
 int rlimit_from_string(const char *s);
 
+const char *ip_tos_to_string(int i);
+int ip_tos_from_string(const char *s);
+
 #endif
commit 6398320759ce4ed84922bb28f715d3c6c66166c4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 00:26:44 2010 +0200

    core: rename struct timestamp to dual_timestamp to avoid name clash with IP system headers

diff --git a/src/dbus-unit.h b/src/dbus-unit.h
index 07641ee..5662d30 100644
--- a/src/dbus-unit.h
+++ b/src/dbus-unit.h
@@ -95,10 +95,10 @@
         { "org.freedesktop.systemd1.Unit", "ActiveState",          bus_unit_append_active_state,   "s",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "SubState",             bus_unit_append_sub_state,      "s",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "FragmentPath",         bus_property_append_string,     "s",    u->meta.fragment_path             }, \
-        { "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_uint64,     "t",    &u->meta.inactive_exit_timestamp  }, \
-        { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_uint64,     "t",    &u->meta.active_enter_timestamp   }, \
-        { "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp",  bus_property_append_uint64,     "t",    &u->meta.active_exit_timestamp    }, \
-        { "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_uint64,    "t",    &u->meta.inactive_enter_timestamp }, \
+        { "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_uint64,     "t",    &u->meta.inactive_exit_timestamp.realtime  }, \
+        { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_uint64,     "t",    &u->meta.active_enter_timestamp.realtime }, \
+        { "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp",  bus_property_append_uint64,     "t",    &u->meta.active_exit_timestamp.realtime    }, \
+        { "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_uint64,    "t",    &u->meta.inactive_enter_timestamp.realtime }, \
         { "org.freedesktop.systemd1.Unit", "CanStart",             bus_unit_append_can_start,      "b",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "CanReload",            bus_unit_append_can_reload,     "b",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "Job",                  bus_unit_append_job,            "(uo)", u                                 }, \
diff --git a/src/execute.c b/src/execute.c
index d5bb8d3..cf71f23 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -1273,7 +1273,7 @@ int exec_spawn(ExecCommand *command,
         log_debug("Forked %s as %lu", command->path, (unsigned long) pid);
 
         command->exec_status.pid = pid;
-        command->exec_status.start_timestamp = now(CLOCK_REALTIME);
+        dual_timestamp_get(&command->exec_status.start_timestamp);
 
         *ret = pid;
         return 0;
@@ -1553,7 +1553,7 @@ void exec_status_fill(ExecStatus *s, pid_t pid, int code, int status) {
         assert(s);
 
         s->pid = pid;
-        s->exit_timestamp = now(CLOCK_REALTIME);
+        dual_timestamp_get(&s->exit_timestamp);
 
         s->code = code;
         s->status = status;
@@ -1575,17 +1575,17 @@ void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
                 "%sPID: %lu\n",
                 prefix, (unsigned long) s->pid);
 
-        if (s->start_timestamp > 0)
+        if (s->start_timestamp.realtime > 0)
                 fprintf(f,
                         "%sStart Timestamp: %s\n",
-                        prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp));
+                        prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
 
-        if (s->exit_timestamp > 0)
+        if (s->exit_timestamp.realtime > 0)
                 fprintf(f,
                         "%sExit Timestamp: %s\n"
                         "%sExit Code: %s\n"
                         "%sExit Status: %i\n",
-                        prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp),
+                        prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
                         prefix, sigchld_code_to_string(s->code),
                         prefix, s->status);
 }
diff --git a/src/execute.h b/src/execute.h
index e618049..841670a 100644
--- a/src/execute.h
+++ b/src/execute.h
@@ -67,8 +67,8 @@ typedef enum ExecOutput {
 } ExecOutput;
 
 struct ExecStatus {
-        usec_t start_timestamp;
-        usec_t exit_timestamp;
+        dual_timestamp start_timestamp;
+        dual_timestamp exit_timestamp;
         pid_t pid;
         int code;     /* as in siginfo_t::si_code */
         int status;   /* as in sigingo_t::si_status */
diff --git a/src/initctl.c b/src/initctl.c
index 3de7fcd..a18cf38 100644
--- a/src/initctl.c
+++ b/src/initctl.c
@@ -290,7 +290,7 @@ static int server_init(Server *s, unsigned n_sockets) {
                         goto fail;
                 }
 
-                f->fd = SD_LISTEN_FDS_START+i;
+                f->fd = fd;
                 LIST_PREPEND(Fifo, fifo, s->fifos, f);
                 f->server = s;
                 s->n_fifos ++;
diff --git a/src/manager.c b/src/manager.c
index f9763c8..b8daffd 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -194,7 +194,7 @@ int manager_new(ManagerRunningAs running_as, bool confirm_spawn, Manager **_m) {
         if (!(m = new0(Manager, 1)))
                 return -ENOMEM;
 
-        timestamp_get(&m->startup_timestamp);
+        dual_timestamp_get(&m->startup_timestamp);
 
         m->running_as = running_as;
         m->confirm_spawn = confirm_spawn;
diff --git a/src/manager.h b/src/manager.h
index 6e74773..eed137b 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -137,7 +137,7 @@ struct Manager {
 
         char **environment;
 
-        timestamp startup_timestamp;
+        dual_timestamp startup_timestamp;
 
         /* Data specific to the device subsystem */
         struct udev* udev;
diff --git a/src/unit.c b/src/unit.c
index c546035..76e8cd7 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -926,7 +926,7 @@ static void retroactively_stop_dependencies(Unit *u) {
 
 void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
         bool unexpected = false;
-        timestamp ts;
+        dual_timestamp ts;
 
         assert(u);
         assert(os < _UNIT_ACTIVE_STATE_MAX);
@@ -939,7 +939,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
          * this function will be called too and the utmp code below
          * relies on that! */
 
-        timestamp_get(&ts);
+        dual_timestamp_get(&ts);
 
         if (os == UNIT_INACTIVE && ns != UNIT_INACTIVE)
                 u->meta.inactive_exit_timestamp = ts;
diff --git a/src/unit.h b/src/unit.h
index fb158d5..70b3c9a 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -153,10 +153,10 @@ struct Meta {
          * the job for it */
         Job *job;
 
-        timestamp inactive_exit_timestamp;
-        timestamp active_enter_timestamp;
-        timestamp active_exit_timestamp;
-        timestamp inactive_enter_timestamp;
+        dual_timestamp inactive_exit_timestamp;
+        dual_timestamp active_enter_timestamp;
+        dual_timestamp active_exit_timestamp;
+        dual_timestamp inactive_enter_timestamp;
 
         /* Counterparts in the cgroup filesystem */
         CGroupBonding *cgroup_bondings;
diff --git a/src/util.c b/src/util.c
index 11ab074..41d8e7f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -75,7 +75,7 @@ usec_t now(clockid_t clock_id) {
         return timespec_load(&ts);
 }
 
-timestamp* timestamp_get(timestamp *ts) {
+dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
         assert(ts);
 
         ts->realtime = now(CLOCK_REALTIME);
diff --git a/src/util.h b/src/util.h
index 2410312..91e0359 100644
--- a/src/util.h
+++ b/src/util.h
@@ -34,10 +34,10 @@
 
 typedef uint64_t usec_t;
 
-typedef struct timestamp {
+typedef struct dual_timestamp {
         usec_t realtime;
         usec_t monotonic;
-} timestamp;
+} dual_timestamp;
 
 #define MSEC_PER_SEC  1000ULL
 #define USEC_PER_SEC  1000000ULL
@@ -60,7 +60,7 @@ typedef struct timestamp {
 
 usec_t now(clockid_t clock);
 
-timestamp* timestamp_get(timestamp *ts);
+dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
 
 usec_t timespec_load(const struct timespec *ts);
 struct timespec *timespec_store(struct timespec *ts, usec_t u);
commit 6398bea5d22a1d53f2fdabbf6fa4dc6f4ac1b6f4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 1 00:24:14 2010 +0200

    build-sys: fix automake version check

diff --git a/bootstrap.sh b/bootstrap.sh
index 6f13ba2..74f814d 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -53,7 +53,7 @@ if type -p colorgcc > /dev/null ; then
 fi
 
 if [ "x$1" = "xam" ] ; then
-    run_versioned automake "$VERSION" -a -c --foreign
+    run_versioned automake "$AM_VERSION" -a -c --foreign
     ./config.status
 else
     rm -rf autom4te.cache


More information about the systemd-commits mailing list