unit.c 80.5 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
                return true;

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

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

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

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

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

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

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

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

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

        if (unit_check_gc(u))
                return;

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

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

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

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

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

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

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

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

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

        set_free(s);
}

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

        assert(u);

349
350
        bus_unit_send_removed_signal(u);

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

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

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

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

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

373
374
375
376
377
        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
378
379
        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
380

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

500
501
        other = unit_follow_merge(other);

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

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

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

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

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

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

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

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

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

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

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

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

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

        return 0;
}

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

        assert(u);
        assert(name);

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

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

                name = s;
        }

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

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

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

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

        return u;
}

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

        assert(u);
        assert(c);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

699
700
701
702
703
704
705
706
707
708
709
710
        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
711
        if (u->load_state == UNIT_LOADED) {
712
713
714
                CGroupBonding *b;
                CGroupAttribute *a;

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

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

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

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

                        free(v);
                }
746

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

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

Lennart Poettering's avatar
Lennart Poettering committed
757

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

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

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

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

        assert(u);

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

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

        assert(u);

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);

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

856
857
858
        return 0;
}

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

        assert(u);

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

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

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

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

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

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

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

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

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

                r = -EINVAL;
                goto fail;
        }

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

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

        return 0;

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

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

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

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
932
/* Errors:
933
934
935
936
 *         -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
937
938
939
 */
int unit_start(Unit *u) {
        UnitActiveState state;
940
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
941
942
943

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
944
        if (u->load_state != UNIT_LOADED)
945
946
                return -EINVAL;

947
948
949
950
        /* 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
951
952
953
954
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

955
956
957
958
959
960
        /* 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
961
                log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);
962
963
964
                return -EALREADY;
        }

965
966
        /* Forward to the main object, if we aren't it. */
        if ((following = unit_following(u))) {
Michal Schmidt's avatar
Michal Schmidt committed
967
                log_debug("Redirecting start request from %s to %s.", u->id, following->id);
968
969
970
971
972
973
974
                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
975
976
977
978
979
980
        /* 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. */

981
        unit_add_to_dbus_queue(u);
982