unit.c 77 KB
Newer Older
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Lennart Poettering's avatar
Lennart Poettering committed
2

3
4
5
6
7
8
/***
  This file is part of systemd.

  Copyright 2010 Lennart Poettering

  systemd is free software; you can redistribute it and/or modify it
9
10
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 2.1 of the License, or
11
12
13
14
15
  (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
16
  Lesser General Public License for more details.
17

18
  You should have received a copy of the GNU Lesser General Public License
19
20
21
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

Lennart Poettering's avatar
Lennart Poettering committed
22
23
24
25
26
27
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/poll.h>
28
29
#include <stdlib.h>
#include <unistd.h>
30
#include <sys/stat.h>
Lennart Poettering's avatar
Lennart Poettering committed
31
32
33
34
35
36
37
38

#include "set.h"
#include "unit.h"
#include "macro.h"
#include "strv.h"
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
39
40
#include "unit-name.h"
#include "specifier.h"
41
#include "dbus-unit.h"
42
#include "special.h"
43
#include "cgroup-util.h"
44
#include "missing.h"
45
#include "cgroup-attr.h"
Lennart Poettering's avatar
Lennart Poettering committed
46
47
48
49
50
51
52
53
54

const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
        [UNIT_SERVICE] = &service_vtable,
        [UNIT_TIMER] = &timer_vtable,
        [UNIT_SOCKET] = &socket_vtable,
        [UNIT_TARGET] = &target_vtable,
        [UNIT_DEVICE] = &device_vtable,
        [UNIT_MOUNT] = &mount_vtable,
        [UNIT_AUTOMOUNT] = &automount_vtable,
Maarten Lankhorst's avatar
Maarten Lankhorst committed
55
        [UNIT_SNAPSHOT] = &snapshot_vtable,
56
57
        [UNIT_SWAP] = &swap_vtable,
        [UNIT_PATH] = &path_vtable
Lennart Poettering's avatar
Lennart Poettering committed
58
59
};

60
Unit *unit_new(Manager *m, size_t size) {
Lennart Poettering's avatar
Lennart Poettering committed
61
62
63
        Unit *u;

        assert(m);
Michal Schmidt's avatar
Michal Schmidt committed
64
        assert(size >= sizeof(Unit));
Lennart Poettering's avatar
Lennart Poettering committed
65

66
67
        u = malloc0(size);
        if (!u)
Lennart Poettering's avatar
Lennart Poettering committed
68
69
                return NULL;

Michal Schmidt's avatar
Michal Schmidt committed
70
71
        u->names = set_new(string_hash_func, string_compare_func);
        if (!u->names) {
Lennart Poettering's avatar
Lennart Poettering committed
72
73
74
75
                free(u);
                return NULL;
        }

Michal Schmidt's avatar
Michal Schmidt committed
76
77
78
79
80
        u->manager = m;
        u->type = _UNIT_TYPE_INVALID;
        u->deserialized_job = _JOB_TYPE_INVALID;
        u->default_dependencies = true;
        u->unit_file_state = _UNIT_FILE_STATE_INVALID;
Lennart Poettering's avatar
Lennart Poettering committed
81
82
83
84

        return u;
}

85
86
87
88
bool unit_has_name(Unit *u, const char *name) {
        assert(u);
        assert(name);

Michal Schmidt's avatar
Michal Schmidt committed
89
        return !!set_get(u->names, (char*) name);
90
91
}

Lennart Poettering's avatar
Lennart Poettering committed
92
93
int unit_add_name(Unit *u, const char *text) {
        UnitType t;
94
        char *s, *i = NULL;
Lennart Poettering's avatar
Lennart Poettering committed
95
96
97
98
99
        int r;

        assert(u);
        assert(text);

100
        if (unit_name_is_template(text)) {
Michal Schmidt's avatar
Michal Schmidt committed
101
                if (!u->instance)
102
                        return -EINVAL;
Lennart Poettering's avatar
Lennart Poettering committed
103

Michal Schmidt's avatar
Michal Schmidt committed
104
                s = unit_name_replace_instance(text, u->instance);
105
106
        } else
                s = strdup(text);
Lennart Poettering's avatar
Lennart Poettering committed
107

108
109
        if (!s)
                return -ENOMEM;
Lennart Poettering's avatar
Lennart Poettering committed
110

111
        if (!unit_name_is_valid(s, false)) {
112
113
114
                r = -EINVAL;
                goto fail;
        }
115

116
        assert_se((t = unit_name_to_type(s)) >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
117

Michal Schmidt's avatar
Michal Schmidt committed
118
        if (u->type != _UNIT_TYPE_INVALID && t != u->type) {
119
120
121
                r = -EINVAL;
                goto fail;
        }
Lennart Poettering's avatar
Lennart Poettering committed
122

123
124
        if ((r = unit_name_to_instance(s, &i)) < 0)
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
125

126
127
        if (i && unit_vtable[t]->no_instances) {
                r = -EINVAL;
128
                goto fail;
129
        }
130

131
132
        /* Ensure that this unit is either instanced or not instanced,
         * but not both. */
Michal Schmidt's avatar
Michal Schmidt committed
133
        if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) {
134
135
136
137
138
                r = -EINVAL;
                goto fail;
        }

        if (unit_vtable[t]->no_alias &&
Michal Schmidt's avatar
Michal Schmidt committed
139
140
            !set_isempty(u->names) &&
            !set_get(u->names, s)) {
141
142
143
144
                r = -EEXIST;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
145
        if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) {
146
147
148
149
                r = -E2BIG;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
150
        if ((r = set_put(u->names, s)) < 0) {
151
152
153
                if (r == -EEXIST)
                        r = 0;
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
154
155
        }

Michal Schmidt's avatar
Michal Schmidt committed
156
157
        if ((r = hashmap_put(u->manager->units, s, u)) < 0) {
                set_remove(u->names, s);
158
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
159
160
        }

Michal Schmidt's avatar
Michal Schmidt committed
161
        if (u->type == _UNIT_TYPE_INVALID) {
Lennart Poettering's avatar
Lennart Poettering committed
162

Michal Schmidt's avatar
Michal Schmidt committed
163
164
165
                u->type = t;
                u->id = s;
                u->instance = i;
166

Michal Schmidt's avatar
Michal Schmidt committed
167
                LIST_PREPEND(Unit, units_by_type, u->manager->units_by_type[t], u);
168
169
170

                if (UNIT_VTABLE(u)->init)
                        UNIT_VTABLE(u)->init(u);
171
172
        } else
                free(i);
Lennart Poettering's avatar
Lennart Poettering committed
173

174
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
175
        return 0;
176
177
178
179
180
181

fail:
        free(s);
        free(i);

        return r;
Lennart Poettering's avatar
Lennart Poettering committed
182
183
}

184
int unit_choose_id(Unit *u, const char *name) {
185
186
        char *s, *t = NULL, *i;
        int r;
187
188
189
190

        assert(u);
        assert(name);

191
192
        if (unit_name_is_template(name)) {

Michal Schmidt's avatar
Michal Schmidt committed
193
                if (!u->instance)
194
195
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
196
                if (!(t = unit_name_replace_instance(name, u->instance)))
197
198
199
200
201
                        return -ENOMEM;

                name = t;
        }

202
        /* Selects one of the names of this unit as the id */
Michal Schmidt's avatar
Michal Schmidt committed
203
        s = set_get(u->names, (char*) name);
204
        free(t);
205

206
        if (!s)
207
208
                return -ENOENT;

209
210
211
        if ((r = unit_name_to_instance(s, &i)) < 0)
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
212
        u->id = s;
213

Michal Schmidt's avatar
Michal Schmidt committed
214
215
        free(u->instance);
        u->instance = i;
216

217
        unit_add_to_dbus_queue(u);
218

219
220
221
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
222
223
224
225
226
227
228
229
int unit_set_description(Unit *u, const char *description) {
        char *s;

        assert(u);

        if (!(s = strdup(description)))
                return -ENOMEM;

Michal Schmidt's avatar
Michal Schmidt committed
230
231
        free(u->description);
        u->description = s;
232
233

        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
234
235
236
        return 0;
}

237
238
239
bool unit_check_gc(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
240
        if (u->load_state == UNIT_STUB)
241
242
                return true;

243
244
245
        if (UNIT_VTABLE(u)->no_gc)
                return true;

Michal Schmidt's avatar
Michal Schmidt committed
246
        if (u->no_gc)
247
248
                return true;

Michal Schmidt's avatar
Michal Schmidt committed
249
        if (u->job)
250
251
252
253
254
255
256
257
258
259
260
261
                return true;

        if (unit_active_state(u) != UNIT_INACTIVE)
                return true;

        if (UNIT_VTABLE(u)->check_gc)
                if (UNIT_VTABLE(u)->check_gc(u))
                        return true;

        return false;
}

Lennart Poettering's avatar
Lennart Poettering committed
262
263
void unit_add_to_load_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
264
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
265

Michal Schmidt's avatar
Michal Schmidt committed
266
        if (u->load_state != UNIT_STUB || u->in_load_queue)
Lennart Poettering's avatar
Lennart Poettering committed
267
268
                return;

Michal Schmidt's avatar
Michal Schmidt committed
269
270
        LIST_PREPEND(Unit, load_queue, u->manager->load_queue, u);
        u->in_load_queue = true;
Lennart Poettering's avatar
Lennart Poettering committed
271
272
}

273
274
275
void unit_add_to_cleanup_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
276
        if (u->in_cleanup_queue)
277
278
                return;

Michal Schmidt's avatar
Michal Schmidt committed
279
280
        LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u);
        u->in_cleanup_queue = true;
281
282
}

283
284
285
void unit_add_to_gc_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
286
        if (u->in_gc_queue || u->in_cleanup_queue)
287
288
289
290
291
                return;

        if (unit_check_gc(u))
                return;

Michal Schmidt's avatar
Michal Schmidt committed
292
293
        LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u);
        u->in_gc_queue = true;
294

Michal Schmidt's avatar
Michal Schmidt committed
295
        u->manager->n_in_gc_queue ++;
296

Michal Schmidt's avatar
Michal Schmidt committed
297
298
        if (u->manager->gc_queue_timestamp <= 0)
                u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
299
300
}

301
302
void unit_add_to_dbus_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
303
        assert(u->type != _UNIT_TYPE_INVALID);
304

Michal Schmidt's avatar
Michal Schmidt committed
305
        if (u->load_state == UNIT_STUB || u->in_dbus_queue)
306
307
                return;

308
        /* Shortcut things if nobody cares */
Michal Schmidt's avatar
Michal Schmidt committed
309
310
        if (!bus_has_subscriber(u->manager)) {
                u->sent_dbus_new_signal = true;
311
312
313
                return;
        }

Michal Schmidt's avatar
Michal Schmidt committed
314
315
        LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
        u->in_dbus_queue = true;
316
317
}

Lennart Poettering's avatar
Lennart Poettering committed
318
319
320
321
322
323
324
325
326
327
328
329
330
static void bidi_set_free(Unit *u, Set *s) {
        Iterator i;
        Unit *other;

        assert(u);

        /* Frees the set and makes sure we are dropped from the
         * inverse pointers */

        SET_FOREACH(other, s, i) {
                UnitDependency d;

                for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
Michal Schmidt's avatar
Michal Schmidt committed
331
                        set_remove(other->dependencies[d], u);
332
333

                unit_add_to_gc_queue(other);
Lennart Poettering's avatar
Lennart Poettering committed
334
335
336
337
338
339
340
341
342
343
344
345
        }

        set_free(s);
}

void unit_free(Unit *u) {
        UnitDependency d;
        Iterator i;
        char *t;

        assert(u);

346
347
        bus_unit_send_removed_signal(u);

Michal Schmidt's avatar
Michal Schmidt committed
348
        if (u->load_state != UNIT_STUB)
349
350
351
                if (UNIT_VTABLE(u)->done)
                        UNIT_VTABLE(u)->done(u);

Michal Schmidt's avatar
Michal Schmidt committed
352
353
        SET_FOREACH(t, u->names, i)
                hashmap_remove_value(u->manager->units, t, u);
Lennart Poettering's avatar
Lennart Poettering committed
354

Michal Schmidt's avatar
Michal Schmidt committed
355
356
        if (u->job)
                job_free(u->job);
357
358

        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
Michal Schmidt's avatar
Michal Schmidt committed
359
                bidi_set_free(u, u->dependencies[d]);
360

Michal Schmidt's avatar
Michal Schmidt committed
361
362
        if (u->type != _UNIT_TYPE_INVALID)
                LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u);
Lennart Poettering's avatar
Lennart Poettering committed
363

Michal Schmidt's avatar
Michal Schmidt committed
364
365
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
366

Michal Schmidt's avatar
Michal Schmidt committed
367
368
        if (u->in_dbus_queue)
                LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
369

Michal Schmidt's avatar
Michal Schmidt committed
370
371
        if (u->in_cleanup_queue)
                LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
372

Michal Schmidt's avatar
Michal Schmidt committed
373
374
375
        if (u->in_gc_queue) {
                LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u);
                u->manager->n_in_gc_queue--;
376
377
        }

Michal Schmidt's avatar
Michal Schmidt committed
378
379
        cgroup_bonding_free_list(u->cgroup_bondings, u->manager->n_reloading <= 0);
        cgroup_attribute_free_list(u->cgroup_attributes);
Lennart Poettering's avatar
Lennart Poettering committed
380

Michal Schmidt's avatar
Michal Schmidt committed
381
382
383
        free(u->description);
        free(u->fragment_path);
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
384

Michal Schmidt's avatar
Michal Schmidt committed
385
        set_free_free(u->names);
Lennart Poettering's avatar
Lennart Poettering committed
386

Michal Schmidt's avatar
Michal Schmidt committed
387
        condition_free_list(u->conditions);
388

Michal Schmidt's avatar
Michal Schmidt committed
389
390
        while (u->refs)
                unit_ref_unset(u->refs);
391

Lennart Poettering's avatar
Lennart Poettering committed
392
393
394
395
396
397
        free(u);
}

UnitActiveState unit_active_state(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
398
        if (u->load_state == UNIT_MERGED)
399
400
401
402
                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
403
         * shortcut failed loading to UNIT_INACTIVE_FAILED. */
Lennart Poettering's avatar
Lennart Poettering committed
404
405
406
407

        return UNIT_VTABLE(u)->active_state(u);
}

408
409
410
411
412
413
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

        return UNIT_VTABLE(u)->sub_state_to_string(u);
}

414
415
416
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
417

418
419
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
420
421

        if (*s)
422
423
424
425
426
427
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
428

429
430
431
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
432

433
434
435
        assert(u);
        assert(other);

Michal Schmidt's avatar
Michal Schmidt committed
436
        complete_move(&u->names, &other->names);
437

Michal Schmidt's avatar
Michal Schmidt committed
438
439
440
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
441

Michal Schmidt's avatar
Michal Schmidt committed
442
443
        SET_FOREACH(t, u->names, i)
                assert_se(hashmap_replace(u->manager->units, t, u) == 0);
Lennart Poettering's avatar
Lennart Poettering committed
444
445
}

446
447
448
static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
        Iterator i;
        Unit *back;
Lennart Poettering's avatar
Lennart Poettering committed
449
        int r;
450
451
452
453
454

        assert(u);
        assert(other);
        assert(d < _UNIT_DEPENDENCY_MAX);

455
        /* Fix backwards pointers */
Michal Schmidt's avatar
Michal Schmidt committed
456
        SET_FOREACH(back, other->dependencies[d], i) {
457
458
459
                UnitDependency k;

                for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++)
Michal Schmidt's avatar
Michal Schmidt committed
460
                        if ((r = set_remove_and_put(back->dependencies[k], other, u)) < 0) {
461
462

                                if (r == -EEXIST)
Michal Schmidt's avatar
Michal Schmidt committed
463
                                        set_remove(back->dependencies[k], other);
464
465
466
467
468
                                else
                                        assert(r == -ENOENT);
                        }
        }

Michal Schmidt's avatar
Michal Schmidt committed
469
        complete_move(&u->dependencies[d], &other->dependencies[d]);
470

Michal Schmidt's avatar
Michal Schmidt committed
471
472
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
473
474
475
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
476
477
478
479
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
480
481
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
482

483
484
        other = unit_follow_merge(other);

485
486
487
        if (other == u)
                return 0;

Michal Schmidt's avatar
Michal Schmidt committed
488
        if (u->type != other->type)
489
490
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
491
        if (!u->instance != !other->instance)
Lennart Poettering's avatar
Lennart Poettering committed
492
493
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
494
495
        if (other->load_state != UNIT_STUB &&
            other->load_state != UNIT_ERROR)
496
                return -EEXIST;
Lennart Poettering's avatar
Lennart Poettering committed
497

Michal Schmidt's avatar
Michal Schmidt committed
498
        if (other->job)
499
500
                return -EEXIST;

501
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
502
503
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
504
        /* Merge names */
505
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
506

507
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
508
509
        while (other->refs)
                unit_ref_set(other->refs, u);
510

Lennart Poettering's avatar
Lennart Poettering committed
511
512
        /* Merge dependencies */
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
513
                merge_dependencies(u, other, d);
Lennart Poettering's avatar
Lennart Poettering committed
514

Michal Schmidt's avatar
Michal Schmidt committed
515
516
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
517

518
519
        /* If there is still some data attached to the other node, we
         * don't need it anymore, and can free it. */
Michal Schmidt's avatar
Michal Schmidt committed
520
        if (other->load_state != UNIT_STUB)
521
522
523
524
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
525
526
527
528
529
530
531
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
532
533
        int r;
        char *s = NULL;
534
535
536
537

        assert(u);
        assert(name);

538
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
539
                if (!u->instance)
540
541
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
542
                if (!(s = unit_name_replace_instance(name, u->instance)))
543
544
545
546
547
                        return -ENOMEM;

                name = s;
        }

Michal Schmidt's avatar
Michal Schmidt committed
548
        if (!(other = manager_get_unit(u->manager, name)))
549
550
551
                r = unit_add_name(u, name);
        else
                r = unit_merge(u, other);
552

553
554
        free(s);
        return r;
555
556
557
558
559
}

Unit* unit_follow_merge(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
560
561
        while (u->load_state == UNIT_MERGED)
                assert_se(u = u->merged_into);
562
563
564
565
566
567
568
569
570
571

        return u;
}

int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
        int r;

        assert(u);
        assert(c);

572
573
        if (c->std_output != EXEC_OUTPUT_KMSG &&
            c->std_output != EXEC_OUTPUT_SYSLOG &&
574
            c->std_output != EXEC_OUTPUT_JOURNAL &&
575
576
            c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
            c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
577
            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
578
            c->std_error != EXEC_OUTPUT_KMSG &&
579
            c->std_error != EXEC_OUTPUT_SYSLOG &&
580
            c->std_error != EXEC_OUTPUT_JOURNAL &&
581
            c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
582
            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
583
            c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
584
585
586
587
588
                return 0;

        /* If syslog or kernel logging is requested, make sure our own
         * logging daemon is run first. */

Michal Schmidt's avatar
Michal Schmidt committed
589
        if (u->manager->running_as == MANAGER_SYSTEM)
590
                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
591
592
                        return r;

Lennart Poettering's avatar
Lennart Poettering committed
593
594
595
596
597
598
        return 0;
}

const char *unit_description(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
599
600
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
601

Michal Schmidt's avatar
Michal Schmidt committed
602
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
603
604
605
606
607
608
}

void unit_dump(Unit *u, FILE *f, const char *prefix) {
        char *t;
        UnitDependency d;
        Iterator i;
609
610
        char *p2;
        const char *prefix2;
611
612
613
614
        char
                timestamp1[FORMAT_TIMESTAMP_MAX],
                timestamp2[FORMAT_TIMESTAMP_MAX],
                timestamp3[FORMAT_TIMESTAMP_MAX],
615
616
                timestamp4[FORMAT_TIMESTAMP_MAX],
                timespan[FORMAT_TIMESPAN_MAX];
617
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
618
619

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
620
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
621
622
623

        if (!prefix)
                prefix = "";
624
625
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
626
627

        fprintf(f,
628
                "%s-> Unit %s:\n"
Lennart Poettering's avatar
Lennart Poettering committed
629
                "%s\tDescription: %s\n"
630
                "%s\tInstance: %s\n"
Lennart Poettering's avatar
Lennart Poettering committed
631
                "%s\tUnit Load State: %s\n"
632
                "%s\tUnit Active State: %s\n"
633
                "%s\tInactive Exit Timestamp: %s\n"
634
                "%s\tActive Enter Timestamp: %s\n"
635
                "%s\tActive Exit Timestamp: %s\n"
636
                "%s\tInactive Enter Timestamp: %s\n"
637
638
                "%s\tGC Check Good: %s\n"
                "%s\tNeed Daemon Reload: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
639
                prefix, u->id,
Lennart Poettering's avatar
Lennart Poettering committed
640
                prefix, unit_description(u),
Michal Schmidt's avatar
Michal Schmidt committed
641
642
                prefix, strna(u->instance),
                prefix, unit_load_state_to_string(u->load_state),
643
                prefix, unit_active_state_to_string(unit_active_state(u)),
Michal Schmidt's avatar
Michal Schmidt committed
644
645
646
647
                prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
                prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
                prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
                prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
648
649
                prefix, yes_no(unit_check_gc(u)),
                prefix, yes_no(unit_need_daemon_reload(u)));
650

Michal Schmidt's avatar
Michal Schmidt committed
651
        SET_FOREACH(t, u->names, i)
Lennart Poettering's avatar
Lennart Poettering committed
652
653
                fprintf(f, "%s\tName: %s\n", prefix, t);

654
        if ((following = unit_following(u)))
Michal Schmidt's avatar
Michal Schmidt committed
655
                fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
656

Michal Schmidt's avatar
Michal Schmidt committed
657
658
        if (u->fragment_path)
                fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
659

Michal Schmidt's avatar
Michal Schmidt committed
660
661
        if (u->job_timeout > 0)
                fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout));
662

Michal Schmidt's avatar
Michal Schmidt committed
663
        condition_dump_list(u->conditions, f, prefix);
664

Michal Schmidt's avatar
Michal Schmidt committed
665
        if (dual_timestamp_is_set(&u->condition_timestamp))
666
667
668
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
669
670
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
671

Lennart Poettering's avatar
Lennart Poettering committed
672
673
674
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
675
676
                SET_FOREACH(other, u->dependencies[d], i)
                        fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
Lennart Poettering's avatar
Lennart Poettering committed
677
678
        }

Michal Schmidt's avatar
Michal Schmidt committed
679
        if (u->load_state == UNIT_LOADED) {
680
681
682
                CGroupBonding *b;
                CGroupAttribute *a;

683
                fprintf(f,
684
                        "%s\tStopWhenUnneeded: %s\n"
685
686
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
687
                        "%s\tDefaultDependencies: %s\n"
688
                        "%s\tOnFailureIsolate: %s\n"
689
690
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
691
692
693
694
695
696
697
698
699
                        prefix, yes_no(u->stop_when_unneeded),
                        prefix, yes_no(u->refuse_manual_start),
                        prefix, yes_no(u->refuse_manual_stop),
                        prefix, yes_no(u->default_dependencies),
                        prefix, yes_no(u->on_failure_isolate),
                        prefix, yes_no(u->ignore_on_isolate),
                        prefix, yes_no(u->ignore_on_snapshot));

                LIST_FOREACH(by_unit, b, u->cgroup_bondings)
700
701
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
702

Michal Schmidt's avatar
Michal Schmidt committed
703
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
704
705
706
707
708
                        char *v = NULL;

                        if (a->map_callback)
                                a->map_callback(a->controller, a->name, a->value, &v);

709
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
710
711
712
713
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
714

715
716
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
717

Michal Schmidt's avatar
Michal Schmidt committed
718
        } else if (u->load_state == UNIT_MERGED)
719
720
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
721
722
723
                        prefix, u->merged_into->id);
        else if (u->load_state == UNIT_ERROR)
                fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
724

Lennart Poettering's avatar
Lennart Poettering committed
725

Michal Schmidt's avatar
Michal Schmidt committed
726
727
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
728

729
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
730
731
732
}

/* Common implementation for multiple backends */
733
int unit_load_fragment_and_dropin(Unit *u) {
734
735
736
737
738
        int r;

        assert(u);

        /* Load a .service file */
739
        if ((r = unit_load_fragment(u)) < 0)
740
741
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
742
        if (u->load_state == UNIT_STUB)
743
744
745
746
747
748
749
750
751
752
                return -ENOENT;

        /* Load drop-in directory data */
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
                return r;

        return 0;
}

/* Common implementation for multiple backends */
753
int unit_load_fragment_and_dropin_optional(Unit *u) {
754
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
755
756
757

        assert(u);

758
759
760
761
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

        /* Load a .service file */
762
        if ((r = unit_load_fragment(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
763
764
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
765
766
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
767

Lennart Poettering's avatar
Lennart Poettering committed
768
        /* Load drop-in directory data */
769
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
770
771
                return r;

772
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
773
774
}

775
int unit_add_default_target_dependency(Unit *u, Unit *target) {
776
777
778
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
779
        if (target->type != UNIT_TARGET)
780
781
                return 0;

Harald Hoyer's avatar
Harald Hoyer committed
782
        /* Only add the dependency if both units are loaded, so that
783
         * that loop check below is reliable */
Michal Schmidt's avatar
Michal Schmidt committed
784
785
        if (u->load_state != UNIT_LOADED ||
            target->load_state != UNIT_LOADED)
786
787
                return 0;

788
789
        /* If either side wants no automatic dependencies, then let's
         * skip this */
Michal Schmidt's avatar
Michal Schmidt committed
790
791
        if (!u->default_dependencies ||
            !target->default_dependencies)
792
793
                return 0;

794
        /* Don't create loops */
Michal Schmidt's avatar
Michal Schmidt committed
795
        if (set_get(target->dependencies[UNIT_BEFORE], u))
796
797
798
799
800
801
                return 0;

        return unit_add_dependency(target, UNIT_AFTER, u, true);
}

static int unit_add_default_dependencies(Unit *u) {
802
803
804
805
806
807
808
        static const UnitDependency deps[] = {
                UNIT_REQUIRED_BY,
                UNIT_REQUIRED_BY_OVERRIDABLE,
                UNIT_WANTED_BY,
                UNIT_BOUND_BY
        };

809
        Unit *target;
810
811
        Iterator i;
        int r;
812
        unsigned k;
813
814
815

        assert(u);

816
        for (k = 0; k < ELEMENTSOF(deps); k++)
Michal Schmidt's avatar
Michal Schmidt committed
817
                SET_FOREACH(target, u->dependencies[deps[k]], i)
818
819
                        if ((r = unit_add_default_target_dependency(u, target)) < 0)
                                return r;
820

821
822
823
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
824
825
826
827
828
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
829
830
831
        if (u->in_load_queue) {
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
                u->in_load_queue = false;
Lennart Poettering's avatar
Lennart Poettering committed
832
833
        }

Michal Schmidt's avatar
Michal Schmidt committed
834
        if (u->type == _UNIT_TYPE_INVALID)
835
836
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
837
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
838
839
                return 0;

840
841
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
842
                        goto fail;
843

Michal Schmidt's avatar
Michal Schmidt committed
844
        if (u->load_state == UNIT_STUB) {
845
846
847
848
                r = -ENOENT;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
849
850
        if (u->load_state == UNIT_LOADED &&
            u->default_dependencies)
851
852
853
                if ((r = unit_add_default_dependencies(u)) < 0)
                        goto fail;

Michal Schmidt's avatar
Michal Schmidt committed
854
855
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
856
857

                log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
Michal Schmidt's avatar
Michal Schmidt committed
858
                          u->id);
859
860
861
862
863

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
864
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
865
866

        unit_add_to_dbus_queue(unit_follow_merge(u));
867
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
868
869
870
871

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
872
873
        u->load_state = UNIT_ERROR;
        u->load_error = r;
874
        unit_add_to_dbus_queue(u);
875
        unit_add_to_gc_queue(u);
876

Michal Schmidt's avatar
Michal Schmidt committed
877
        log_debug("Failed to load configuration for %s: %s", u->id, strerror(-r));
878

Lennart Poettering's avatar
Lennart Poettering committed
879
880
881
        return r;
}

882
883
884
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
885
886
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
887

Michal Schmidt's avatar
Michal Schmidt committed
888
        return u->condition_result;
889
890
}

Lennart Poettering's avatar
Lennart Poettering committed
891
/* Errors:
892
893
894
895
 *         -EBADR:     This unit type does not support starting.
 *         -EALREADY:  Unit is already started.
 *         -EAGAIN:    An operation is already in progress. Retry later.
 *         -ECANCELED: Too many requests for now.
Lennart Poettering's avatar
Lennart Poettering committed
896
897
898
 */
int unit_start(Unit *u) {
        UnitActiveState state;
899
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
900
901
902

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
903
        if (u->load_state != UNIT_LOADED)
904
905
                return -EINVAL;

906
907
908
909
        /* If this is already 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 we need to
         * wait for units and when waiting is finished. */
Lennart Poettering's avatar
Lennart Poettering committed
910
911
912
913
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

914
915
916
917
918
919
        /* If the conditions failed, don't do anything at all. If we
         * already are activating this call might still be useful to
         * speed up activation in case there is some hold-off time,
         * but we don't want to recheck the condition in that case. */
        if (state != UNIT_ACTIVATING &&
            !unit_condition_test(u)) {
Michal Schmidt's avatar
Michal Schmidt committed
920
                log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);
921
922
923
                return -EALREADY;
        }

924
925
        /* Forward to the main object, if we aren't it. */
        if ((following = unit_following(u))) {
Michal Schmidt's avatar
Michal Schmidt committed
926
                log_debug("Redirecting start request from %s to %s.", u->id, following->id);
927
928
929
930
931
932
933
                return unit_start(following);
        }

        /* If it is stopped, but we cannot start it, then fail */
        if (!UNIT_VTABLE(u)->start)
                return -EBADR;

Lennart Poettering's avatar
Lennart Poettering committed
934
935
936
937
938
939
        /* We don't suppress calls to ->start() here when we are
         * already starting, to allow this request to be used as a
         * "hurry up" call, for example when the unit is in some "auto
         * restart" state where it waits for a holdoff timer to elapse
         * before it will start again. */

940
        unit_add_to_dbus_queue(u);
941

942
        unit_status_printf(u, NULL, "Starting %s...", unit_description(u));
Lennart Poettering's avatar
Lennart Poettering committed
943
944
945
946
947
948
949
950
951
        return UNIT_VTABLE(u)->start(u);
}

bool unit_can_start(Unit *u) {
        assert(u);

        return !!UNIT_VTABLE(u)->start;
}

952
953
954
955
bool unit_can_isolate(Unit *u) {
        assert(u);

        return unit_can_start(u) &&
Michal Schmidt's avatar
Michal Schmidt committed
956
                u->allow_isolate;
957
958
}

Lennart Poettering's avatar
Lennart Poettering committed
959
960
961
962
963
964
965
/* Errors:
 *         -EBADR:    This unit type does not support stopping.
 *         -EALREADY: Unit is already stopped.
 *         -EAGAIN:   An operation is already in progress. Retry later.
 */
int unit_stop(Unit *u) {
        UnitActiveState state;
966
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
967
968
969
970

        assert(u);

        state = unit_active_state(u);
971
        if (UNIT_IS_INACTIVE_OR_FAILED(state))
Lennart Poettering's avatar
Lennart Poettering committed
972
973
                return -EALREADY;

974
        if ((following = unit_following(u))) {
Michal Schmidt's avatar
Michal Schmidt committed
975
                log_debug("Redirecting stop request from %s to %s.", u->id, following->id);