unit.c 78.3 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
357
358
359
        if (u->job) {
                Job *j = u->job;
                job_uninstall(j);
                job_free(j);
        }
360
361

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

Michal Schmidt's avatar
Michal Schmidt committed
364
365
        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
366

Michal Schmidt's avatar
Michal Schmidt committed
367
368
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
369

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

Michal Schmidt's avatar
Michal Schmidt committed
373
374
        if (u->in_cleanup_queue)
                LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
375

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

Michal Schmidt's avatar
Michal Schmidt committed
381
382
        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
383

Michal Schmidt's avatar
Michal Schmidt committed
384
385
386
        free(u->description);
        free(u->fragment_path);
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
387

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

Michal Schmidt's avatar
Michal Schmidt committed
390
        condition_free_list(u->conditions);
391

Michal Schmidt's avatar
Michal Schmidt committed
392
393
        while (u->refs)
                unit_ref_unset(u->refs);
394

Lennart Poettering's avatar
Lennart Poettering committed
395
396
397
398
399
400
        free(u);
}

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

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

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

411
412
413
414
415
416
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

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

417
418
419
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
420

421
422
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
423
424

        if (*s)
425
426
427
428
429
430
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
431

432
433
434
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
435

436
437
438
        assert(u);
        assert(other);

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

Michal Schmidt's avatar
Michal Schmidt committed
441
442
443
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
444

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

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

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
474
475
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
476
477
478
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
479
480
481
482
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
483
484
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
485

486
487
        other = unit_follow_merge(other);

488
489
490
        if (other == u)
                return 0;

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

Michal Schmidt's avatar
Michal Schmidt committed
494
        if (!u->instance != !other->instance)
Lennart Poettering's avatar
Lennart Poettering committed
495
496
                return -EINVAL;

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

Michal Schmidt's avatar
Michal Schmidt committed
501
        if (other->job)
502
503
                return -EEXIST;

504
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
505
506
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
507
        /* Merge names */
508
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
509

510
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
511
512
        while (other->refs)
                unit_ref_set(other->refs, u);
513

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

Michal Schmidt's avatar
Michal Schmidt committed
518
519
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
520

521
522
        /* 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
523
        if (other->load_state != UNIT_STUB)
524
525
526
527
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
528
529
530
531
532
533
534
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
535
536
        int r;
        char *s = NULL;
537
538
539
540

        assert(u);
        assert(name);

541
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
542
                if (!u->instance)
543
544
                        return -EINVAL;

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

                name = s;
        }

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

556
557
        free(s);
        return r;
558
559
560
561
562
}

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

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

        return u;
}

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

        assert(u);
        assert(c);

575
576
        if (c->std_output != EXEC_OUTPUT_KMSG &&
            c->std_output != EXEC_OUTPUT_SYSLOG &&
577
            c->std_output != EXEC_OUTPUT_JOURNAL &&
578
579
            c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
            c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
580
            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
581
            c->std_error != EXEC_OUTPUT_KMSG &&
582
            c->std_error != EXEC_OUTPUT_SYSLOG &&
583
            c->std_error != EXEC_OUTPUT_JOURNAL &&
584
            c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
585
            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
586
            c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
587
588
589
590
591
                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
592
        if (u->manager->running_as == MANAGER_SYSTEM)
593
                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
594
595
                        return r;

Lennart Poettering's avatar
Lennart Poettering committed
596
597
598
599
600
601
        return 0;
}

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

Michal Schmidt's avatar
Michal Schmidt committed
602
603
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
604

Michal Schmidt's avatar
Michal Schmidt committed
605
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
606
607
608
609
610
611
}

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

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
623
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
624
625
626

        if (!prefix)
                prefix = "";
627
628
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
629
630

        fprintf(f,
631
                "%s-> Unit %s:\n"
Lennart Poettering's avatar
Lennart Poettering committed
632
                "%s\tDescription: %s\n"
633
                "%s\tInstance: %s\n"
Lennart Poettering's avatar
Lennart Poettering committed
634
                "%s\tUnit Load State: %s\n"
635
                "%s\tUnit Active State: %s\n"
636
                "%s\tInactive Exit Timestamp: %s\n"
637
                "%s\tActive Enter Timestamp: %s\n"
638
                "%s\tActive Exit Timestamp: %s\n"
639
                "%s\tInactive Enter Timestamp: %s\n"
640
641
                "%s\tGC Check Good: %s\n"
                "%s\tNeed Daemon Reload: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
642
                prefix, u->id,
Lennart Poettering's avatar
Lennart Poettering committed
643
                prefix, unit_description(u),
Michal Schmidt's avatar
Michal Schmidt committed
644
645
                prefix, strna(u->instance),
                prefix, unit_load_state_to_string(u->load_state),
646
                prefix, unit_active_state_to_string(unit_active_state(u)),
Michal Schmidt's avatar
Michal Schmidt committed
647
648
649
650
                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)),
651
652
                prefix, yes_no(unit_check_gc(u)),
                prefix, yes_no(unit_need_daemon_reload(u)));
653

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

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

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

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
675
676
677
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
678
679
                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
680
681
        }

Michal Schmidt's avatar
Michal Schmidt committed
682
        if (u->load_state == UNIT_LOADED) {
683
684
685
                CGroupBonding *b;
                CGroupAttribute *a;

686
                fprintf(f,
687
                        "%s\tStopWhenUnneeded: %s\n"
688
689
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
690
                        "%s\tDefaultDependencies: %s\n"
691
                        "%s\tOnFailureIsolate: %s\n"
692
693
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
694
695
696
697
698
699
700
701
702
                        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)
703
704
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
705

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

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

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

                        free(v);
                }
717

718
719
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
720

Michal Schmidt's avatar
Michal Schmidt committed
721
        } else if (u->load_state == UNIT_MERGED)
722
723
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
724
725
726
                        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));
727

Lennart Poettering's avatar
Lennart Poettering committed
728

Michal Schmidt's avatar
Michal Schmidt committed
729
730
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
731

732
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
733
734
735
}

/* Common implementation for multiple backends */
736
int unit_load_fragment_and_dropin(Unit *u) {
737
738
739
740
741
        int r;

        assert(u);

        /* Load a .service file */
742
        if ((r = unit_load_fragment(u)) < 0)
743
744
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
745
        if (u->load_state == UNIT_STUB)
746
747
748
749
750
751
752
753
754
755
                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 */
756
int unit_load_fragment_and_dropin_optional(Unit *u) {
757
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
758
759
760

        assert(u);

761
762
763
764
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
768
769
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
770

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

775
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
776
777
}

778
int unit_add_default_target_dependency(Unit *u, Unit *target) {
779
780
781
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
782
        if (target->type != UNIT_TARGET)
783
784
                return 0;

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

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

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

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

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

812
        Unit *target;
813
814
        Iterator i;
        int r;
815
        unsigned k;
816
817
818

        assert(u);

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

824
825
826
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
827
828
829
830
831
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
832
833
834
        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
835
836
        }

Michal Schmidt's avatar
Michal Schmidt committed
837
        if (u->type == _UNIT_TYPE_INVALID)
838
839
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
840
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
841
842
                return 0;

843
844
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
845
                        goto fail;
846

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

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

Michal Schmidt's avatar
Michal Schmidt committed
857
858
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
859
860

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

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
867
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
868
869

        unit_add_to_dbus_queue(unit_follow_merge(u));
870
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
871
872
873
874

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
875
876
        u->load_state = UNIT_ERROR;
        u->load_error = r;
877
        unit_add_to_dbus_queue(u);
878
        unit_add_to_gc_queue(u);
879

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

Lennart Poettering's avatar
Lennart Poettering committed
882
883
884
        return r;
}

885
886
887
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
888
889
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
890

Michal Schmidt's avatar
Michal Schmidt committed
891
        return u->condition_result;
892
893
}

Lennart Poettering's avatar
Lennart Poettering committed
894
/* Errors:
895
896
897
898
 *         -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
899
900
901
 */
int unit_start(Unit *u) {
        UnitActiveState state;
902
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
903
904
905

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
906
        if (u->load_state != UNIT_LOADED)
907
908
                return -EINVAL;

909
910
911
912
        /* 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
913
914
915
916
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

917
918
919
920
921
922
        /* 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
923
                log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);
924
925
926
                return -EALREADY;
        }

927
928
        /* Forward to the main object, if we aren't it. */
        if ((following = unit_following(u))) {
Michal Schmidt's avatar
Michal Schmidt committed
929
                log_debug("Redirecting start request from %s to %s.", u->id, following->id);
930
931
932
933
934
935
936
                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
937
938
939
940
941
942
        /* 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. */

943
        unit_add_to_dbus_queue(u);
944

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

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

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

955
956
957
958
bool unit_can_isolate(Unit *u) {
        assert(u);

        return unit_can_start(u) &&
Michal Schmidt's avatar
Michal Schmidt committed
959
                u->allow_isolate;
960
961
}

Lennart Poettering's avatar
Lennart Poettering committed
962
963
964
965
966
967
968
/* 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;
969
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
970
971
972
973

        assert(u);

        state = unit_active_state(u);
974
        if (UNIT_IS_INACTIVE_OR_FAILED(state))
Lennart Poettering's avatar
Lennart Poettering committed
975
976
                return -EALREADY;

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