unit.c 80.9 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

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

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
56
        [UNIT_SNAPSHOT] = &snapshot_vtable,
57
58
        [UNIT_SWAP] = &swap_vtable,
        [UNIT_PATH] = &path_vtable
Lennart Poettering's avatar
Lennart Poettering committed
59
60
};

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
77
78
79
80
81
        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
82
83
84
85

        return u;
}

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

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

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

        assert(u);
        assert(text);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);
        assert(name);

192
193
        if (unit_name_is_template(name)) {

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

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

                name = t;
        }

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

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

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

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

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

218
        unit_add_to_dbus_queue(u);
219

220
221
222
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
223
224
225
226
227
228
229
230
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
231
232
        free(u->description);
        u->description = s;
233
234

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
250
        if (u->job)
251
252
                return true;

253
254
255
        if (u->nop_job)
                return true;

256
257
258
259
260
261
262
263
264
265
        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
266
267
void unit_add_to_load_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
268
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
269

Michal Schmidt's avatar
Michal Schmidt committed
270
        if (u->load_state != UNIT_STUB || u->in_load_queue)
Lennart Poettering's avatar
Lennart Poettering committed
271
272
                return;

Michal Schmidt's avatar
Michal Schmidt committed
273
274
        LIST_PREPEND(Unit, load_queue, u->manager->load_queue, u);
        u->in_load_queue = true;
Lennart Poettering's avatar
Lennart Poettering committed
275
276
}

277
278
279
void unit_add_to_cleanup_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
280
        if (u->in_cleanup_queue)
281
282
                return;

Michal Schmidt's avatar
Michal Schmidt committed
283
284
        LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u);
        u->in_cleanup_queue = true;
285
286
}

287
288
289
void unit_add_to_gc_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
290
        if (u->in_gc_queue || u->in_cleanup_queue)
291
292
293
294
295
                return;

        if (unit_check_gc(u))
                return;

Michal Schmidt's avatar
Michal Schmidt committed
296
297
        LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u);
        u->in_gc_queue = true;
298

Michal Schmidt's avatar
Michal Schmidt committed
299
        u->manager->n_in_gc_queue ++;
300

Michal Schmidt's avatar
Michal Schmidt committed
301
302
        if (u->manager->gc_queue_timestamp <= 0)
                u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
303
304
}

305
306
void unit_add_to_dbus_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
307
        assert(u->type != _UNIT_TYPE_INVALID);
308

Michal Schmidt's avatar
Michal Schmidt committed
309
        if (u->load_state == UNIT_STUB || u->in_dbus_queue)
310
311
                return;

312
        /* Shortcut things if nobody cares */
Michal Schmidt's avatar
Michal Schmidt committed
313
314
        if (!bus_has_subscriber(u->manager)) {
                u->sent_dbus_new_signal = true;
315
316
317
                return;
        }

Michal Schmidt's avatar
Michal Schmidt committed
318
319
        LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
        u->in_dbus_queue = true;
320
321
}

Lennart Poettering's avatar
Lennart Poettering committed
322
323
324
325
326
327
328
329
330
331
332
333
334
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
335
                        set_remove(other->dependencies[d], u);
336
337

                unit_add_to_gc_queue(other);
Lennart Poettering's avatar
Lennart Poettering committed
338
339
340
341
342
343
344
345
346
347
348
349
        }

        set_free(s);
}

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

        assert(u);

350
351
        bus_unit_send_removed_signal(u);

Michal Schmidt's avatar
Michal Schmidt committed
352
        if (u->load_state != UNIT_STUB)
353
354
355
                if (UNIT_VTABLE(u)->done)
                        UNIT_VTABLE(u)->done(u);

Michal Schmidt's avatar
Michal Schmidt committed
356
357
        SET_FOREACH(t, u->names, i)
                hashmap_remove_value(u->manager->units, t, u);
Lennart Poettering's avatar
Lennart Poettering committed
358

Michal Schmidt's avatar
Michal Schmidt committed
359
360
361
362
363
        if (u->job) {
                Job *j = u->job;
                job_uninstall(j);
                job_free(j);
        }
364

365
366
367
368
369
370
        if (u->nop_job) {
                Job *j = u->nop_job;
                job_uninstall(j);
                job_free(j);
        }

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

374
375
376
377
378
        if (u->requires_mounts_for) {
                LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
                strv_free(u->requires_mounts_for);
        }

Michal Schmidt's avatar
Michal Schmidt committed
379
380
        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
381

Michal Schmidt's avatar
Michal Schmidt committed
382
383
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
384

Michal Schmidt's avatar
Michal Schmidt committed
385
386
        if (u->in_dbus_queue)
                LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
387

Michal Schmidt's avatar
Michal Schmidt committed
388
389
        if (u->in_cleanup_queue)
                LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
390

Michal Schmidt's avatar
Michal Schmidt committed
391
392
393
        if (u->in_gc_queue) {
                LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u);
                u->manager->n_in_gc_queue--;
394
395
        }

Michal Schmidt's avatar
Michal Schmidt committed
396
397
        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
398

Michal Schmidt's avatar
Michal Schmidt committed
399
400
401
        free(u->description);
        free(u->fragment_path);
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
402

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

Michal Schmidt's avatar
Michal Schmidt committed
405
        condition_free_list(u->conditions);
406

Michal Schmidt's avatar
Michal Schmidt committed
407
408
        while (u->refs)
                unit_ref_unset(u->refs);
409

Lennart Poettering's avatar
Lennart Poettering committed
410
411
412
413
414
415
        free(u);
}

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

Michal Schmidt's avatar
Michal Schmidt committed
416
        if (u->load_state == UNIT_MERGED)
417
418
419
420
                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
421
         * shortcut failed loading to UNIT_INACTIVE_FAILED. */
Lennart Poettering's avatar
Lennart Poettering committed
422
423
424
425

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

426
427
428
429
430
431
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

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

432
433
434
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
435

436
437
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
438
439

        if (*s)
440
441
442
443
444
445
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
446

447
448
449
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
450

451
452
453
        assert(u);
        assert(other);

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

Michal Schmidt's avatar
Michal Schmidt committed
456
457
458
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
459

Michal Schmidt's avatar
Michal Schmidt committed
460
461
        SET_FOREACH(t, u->names, i)
                assert_se(hashmap_replace(u->manager->units, t, u) == 0);
Lennart Poettering's avatar
Lennart Poettering committed
462
463
}

464
465
466
static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
        Iterator i;
        Unit *back;
Lennart Poettering's avatar
Lennart Poettering committed
467
        int r;
468
469
470
471
472

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

473
        /* Fix backwards pointers */
Michal Schmidt's avatar
Michal Schmidt committed
474
        SET_FOREACH(back, other->dependencies[d], i) {
475
476
477
                UnitDependency k;

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

                                if (r == -EEXIST)
Michal Schmidt's avatar
Michal Schmidt committed
481
                                        set_remove(back->dependencies[k], other);
482
483
484
485
486
                                else
                                        assert(r == -ENOENT);
                        }
        }

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

Michal Schmidt's avatar
Michal Schmidt committed
489
490
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
491
492
493
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
494
495
496
497
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
498
499
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
500

501
502
        other = unit_follow_merge(other);

503
504
505
        if (other == u)
                return 0;

Michal Schmidt's avatar
Michal Schmidt committed
506
        if (u->type != other->type)
507
508
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
509
        if (!u->instance != !other->instance)
Lennart Poettering's avatar
Lennart Poettering committed
510
511
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
512
513
        if (other->load_state != UNIT_STUB &&
            other->load_state != UNIT_ERROR)
514
                return -EEXIST;
Lennart Poettering's avatar
Lennart Poettering committed
515

Michal Schmidt's avatar
Michal Schmidt committed
516
        if (other->job)
517
518
                return -EEXIST;

519
520
521
        if (other->nop_job)
                return -EEXIST;

522
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
523
524
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
525
        /* Merge names */
526
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
527

528
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
529
530
        while (other->refs)
                unit_ref_set(other->refs, u);
531

Lennart Poettering's avatar
Lennart Poettering committed
532
533
        /* Merge dependencies */
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
534
                merge_dependencies(u, other, d);
Lennart Poettering's avatar
Lennart Poettering committed
535

Michal Schmidt's avatar
Michal Schmidt committed
536
537
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
538

539
540
        /* 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
541
        if (other->load_state != UNIT_STUB)
542
543
544
545
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
546
547
548
549
550
551
552
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
553
554
        int r;
        char *s = NULL;
555
556
557
558

        assert(u);
        assert(name);

559
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
560
                if (!u->instance)
561
562
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
563
                if (!(s = unit_name_replace_instance(name, u->instance)))
564
565
566
567
568
                        return -ENOMEM;

                name = s;
        }

Michal Schmidt's avatar
Michal Schmidt committed
569
        if (!(other = manager_get_unit(u->manager, name)))
570
571
572
                r = unit_add_name(u, name);
        else
                r = unit_merge(u, other);
573

574
575
        free(s);
        return r;
576
577
578
579
580
}

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

Michal Schmidt's avatar
Michal Schmidt committed
581
582
        while (u->load_state == UNIT_MERGED)
                assert_se(u = u->merged_into);
583
584
585
586
587
588
589
590
591
592

        return u;
}

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

        assert(u);
        assert(c);

593
594
        if (c->std_output != EXEC_OUTPUT_KMSG &&
            c->std_output != EXEC_OUTPUT_SYSLOG &&
595
            c->std_output != EXEC_OUTPUT_JOURNAL &&
596
597
            c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
            c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
598
            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
599
            c->std_error != EXEC_OUTPUT_KMSG &&
600
            c->std_error != EXEC_OUTPUT_SYSLOG &&
601
            c->std_error != EXEC_OUTPUT_JOURNAL &&
602
            c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
603
            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
604
            c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
605
606
607
608
609
                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
610
        if (u->manager->running_as == MANAGER_SYSTEM)
611
                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
612
613
                        return r;

Lennart Poettering's avatar
Lennart Poettering committed
614
615
616
617
618
619
        return 0;
}

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

Michal Schmidt's avatar
Michal Schmidt committed
620
621
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
622

Michal Schmidt's avatar
Michal Schmidt committed
623
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
624
625
626
627
628
629
}

void unit_dump(Unit *u, FILE *f, const char *prefix) {
        char *t;
        UnitDependency d;
        Iterator i;
630
631
        char *p2;
        const char *prefix2;
632
633
634
635
        char
                timestamp1[FORMAT_TIMESTAMP_MAX],
                timestamp2[FORMAT_TIMESTAMP_MAX],
                timestamp3[FORMAT_TIMESTAMP_MAX],
636
637
                timestamp4[FORMAT_TIMESTAMP_MAX],
                timespan[FORMAT_TIMESPAN_MAX];
638
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
639
640

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
641
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
642
643
644

        if (!prefix)
                prefix = "";
645
646
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
647
648

        fprintf(f,
649
                "%s-> Unit %s:\n"
Lennart Poettering's avatar
Lennart Poettering committed
650
                "%s\tDescription: %s\n"
651
                "%s\tInstance: %s\n"
Lennart Poettering's avatar
Lennart Poettering committed
652
                "%s\tUnit Load State: %s\n"
653
                "%s\tUnit Active State: %s\n"
654
                "%s\tInactive Exit Timestamp: %s\n"
655
                "%s\tActive Enter Timestamp: %s\n"
656
                "%s\tActive Exit Timestamp: %s\n"
657
                "%s\tInactive Enter Timestamp: %s\n"
658
659
                "%s\tGC Check Good: %s\n"
                "%s\tNeed Daemon Reload: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
660
                prefix, u->id,
Lennart Poettering's avatar
Lennart Poettering committed
661
                prefix, unit_description(u),
Michal Schmidt's avatar
Michal Schmidt committed
662
663
                prefix, strna(u->instance),
                prefix, unit_load_state_to_string(u->load_state),
664
                prefix, unit_active_state_to_string(unit_active_state(u)),
Michal Schmidt's avatar
Michal Schmidt committed
665
666
667
668
                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)),
669
670
                prefix, yes_no(unit_check_gc(u)),
                prefix, yes_no(unit_need_daemon_reload(u)));
671

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
686
        if (dual_timestamp_is_set(&u->condition_timestamp))
687
688
689
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
690
691
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
692

Lennart Poettering's avatar
Lennart Poettering committed
693
694
695
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
696
697
                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
698
699
        }

700
701
702
703
704
705
706
707
708
709
710
711
        if (!strv_isempty(u->requires_mounts_for)) {
                char **j;

                fprintf(f,
                        "%s\tRequiresMountsFor:", prefix);

                STRV_FOREACH(j, u->requires_mounts_for)
                        fprintf(f, " %s", *j);

                fputs("\n", f);
        }

Michal Schmidt's avatar
Michal Schmidt committed
712
        if (u->load_state == UNIT_LOADED) {
713
714
715
                CGroupBonding *b;
                CGroupAttribute *a;

716
                fprintf(f,
717
                        "%s\tStopWhenUnneeded: %s\n"
718
719
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
720
                        "%s\tDefaultDependencies: %s\n"
721
                        "%s\tOnFailureIsolate: %s\n"
722
723
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
724
725
726
727
728
729
730
731
732
                        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)
733
734
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
735

Michal Schmidt's avatar
Michal Schmidt committed
736
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
737
738
739
740
741
                        char *v = NULL;

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

742
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
743
744
745
746
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
747

748
749
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
750

Michal Schmidt's avatar
Michal Schmidt committed
751
        } else if (u->load_state == UNIT_MERGED)
752
753
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
754
755
756
                        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));
757

Lennart Poettering's avatar
Lennart Poettering committed
758

Michal Schmidt's avatar
Michal Schmidt committed
759
760
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
761

762
763
764
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

765
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
766
767
768
}

/* Common implementation for multiple backends */
769
int unit_load_fragment_and_dropin(Unit *u) {
770
771
772
773
774
        int r;

        assert(u);

        /* Load a .service file */
775
        if ((r = unit_load_fragment(u)) < 0)
776
777
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
778
        if (u->load_state == UNIT_STUB)
779
780
781
782
783
784
785
786
787
788
                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 */
789
int unit_load_fragment_and_dropin_optional(Unit *u) {
790
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
791
792
793

        assert(u);

794
795
796
797
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
801
802
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
803

Lennart Poettering's avatar
Lennart Poettering committed
804
        /* Load drop-in directory data */
805
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
806
807
                return r;

808
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
809
810
}

811
int unit_add_default_target_dependency(Unit *u, Unit *target) {
812
813
814
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
815
        if (target->type != UNIT_TARGET)
816
817
                return 0;

Harald Hoyer's avatar
Harald Hoyer committed
818
        /* Only add the dependency if both units are loaded, so that
819
         * that loop check below is reliable */
Michal Schmidt's avatar
Michal Schmidt committed
820
821
        if (u->load_state != UNIT_LOADED ||
            target->load_state != UNIT_LOADED)
822
823
                return 0;

824
825
        /* If either side wants no automatic dependencies, then let's
         * skip this */
Michal Schmidt's avatar
Michal Schmidt committed
826
827
        if (!u->default_dependencies ||
            !target->default_dependencies)
828
829
                return 0;

830
        /* Don't create loops */
Michal Schmidt's avatar
Michal Schmidt committed
831
        if (set_get(target->dependencies[UNIT_BEFORE], u))
832
833
834
835
836
837
                return 0;

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

static int unit_add_default_dependencies(Unit *u) {
838
839
840
841
842
843
844
        static const UnitDependency deps[] = {
                UNIT_REQUIRED_BY,
                UNIT_REQUIRED_BY_OVERRIDABLE,
                UNIT_WANTED_BY,
                UNIT_BOUND_BY
        };

845
        Unit *target;
846
847
        Iterator i;
        int r;
848
        unsigned k;
849
850
851

        assert(u);

852
        for (k = 0; k < ELEMENTSOF(deps); k++)
Michal Schmidt's avatar
Michal Schmidt committed
853
                SET_FOREACH(target, u->dependencies[deps[k]], i)
854
855
                        if ((r = unit_add_default_target_dependency(u, target)) < 0)
                                return r;
856

857
858
859
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
860
861
862
863
864
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
865
866
867
        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
868
869
        }

Michal Schmidt's avatar
Michal Schmidt committed
870
        if (u->type == _UNIT_TYPE_INVALID)
871
872
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
873
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
874
875
                return 0;

876
877
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
878
                        goto fail;
879

Michal Schmidt's avatar
Michal Schmidt committed
880
        if (u->load_state == UNIT_STUB) {
881
882
883
884
                r = -ENOENT;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
885
886
        if (u->load_state == UNIT_LOADED &&
            u->default_dependencies)
887
888
889
                if ((r = unit_add_default_dependencies(u)) < 0)
                        goto fail;

890
891
892
893
894
895
        if (u->load_state == UNIT_LOADED) {
                r = unit_add_mount_links(u);
                if (r < 0)
                        return r;
        }

Michal Schmidt's avatar
Michal Schmidt committed
896
897
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
898
899

                log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
Michal Schmidt's avatar
Michal Schmidt committed
900
                          u->id);
901
902
903
904
905

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
906
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
907
908

        unit_add_to_dbus_queue(unit_follow_merge(u));
909
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
910
911
912
913

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
914
915
        u->load_state = UNIT_ERROR;
        u->load_error = r;
916
        unit_add_to_dbus_queue(u);
917
        unit_add_to_gc_queue(u);
918

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

Lennart Poettering's avatar
Lennart Poettering committed
921
922
923
        return r;
}

924
925
926
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
927
928
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
929

Michal Schmidt's avatar
Michal Schmidt committed
930
        return u->condition_result;
931
932
}

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
static void unit_status_print_starting_stopping(Unit *u, bool stopping) {
        const UnitStatusMessageFormats *format_table;
        const char *format;

        format_table = &UNIT_VTABLE(u)->status_message_formats;
        if (!format_table)
                return;

        format = format_table->starting_stopping[stopping];
        if (!format)
                return;

        unit_status_printf(u, "", format, unit_description(u));
}

Lennart Poettering's avatar
Lennart Poettering committed
948
/* Errors:
949
950
951
952
 *         -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
953
954
955
 */
int unit_start(Unit *u) {
        UnitActiveState state;
956
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
957
958
959

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
960
        if (u->load_state != UNIT_LOADED)
961
962
                return -EINVAL;

963
964
965
966
        /* 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
967
968
969
970
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

971
972
973
974
975
976
        /* 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
977
                log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);
978
979
980
                return -EALREADY;
        }

981
982
        /* Forward to the main object, if we aren't it. */
        if ((following = unit_following(u))) {
Michal Schmidt's avatar
Michal Schmidt committed
983
                log_debug("Redirecting start request from %s to %s.", u->id, following->id);
984
985
986
                return