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

Michal Schmidt's avatar
Michal Schmidt committed
373
374
        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
375

Michal Schmidt's avatar
Michal Schmidt committed
376
377
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
378

Michal Schmidt's avatar
Michal Schmidt committed
379
380
        if (u->in_dbus_queue)
                LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
381

Michal Schmidt's avatar
Michal Schmidt committed
382
383
        if (u->in_cleanup_queue)
                LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
384

Michal Schmidt's avatar
Michal Schmidt committed
385
386
387
        if (u->in_gc_queue) {
                LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u);
                u->manager->n_in_gc_queue--;
388
389
        }

Michal Schmidt's avatar
Michal Schmidt committed
390
391
        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
392

Michal Schmidt's avatar
Michal Schmidt committed
393
394
395
        free(u->description);
        free(u->fragment_path);
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
396

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

Michal Schmidt's avatar
Michal Schmidt committed
399
        condition_free_list(u->conditions);
400

Michal Schmidt's avatar
Michal Schmidt committed
401
402
        while (u->refs)
                unit_ref_unset(u->refs);
403

Lennart Poettering's avatar
Lennart Poettering committed
404
405
406
407
408
409
        free(u);
}

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

Michal Schmidt's avatar
Michal Schmidt committed
410
        if (u->load_state == UNIT_MERGED)
411
412
413
414
                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
415
         * shortcut failed loading to UNIT_INACTIVE_FAILED. */
Lennart Poettering's avatar
Lennart Poettering committed
416
417
418
419

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

420
421
422
423
424
425
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

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

426
427
428
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
429

430
431
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
432
433

        if (*s)
434
435
436
437
438
439
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
440

441
442
443
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
444

445
446
447
        assert(u);
        assert(other);

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

Michal Schmidt's avatar
Michal Schmidt committed
450
451
452
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
453

Michal Schmidt's avatar
Michal Schmidt committed
454
455
        SET_FOREACH(t, u->names, i)
                assert_se(hashmap_replace(u->manager->units, t, u) == 0);
Lennart Poettering's avatar
Lennart Poettering committed
456
457
}

458
459
460
static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
        Iterator i;
        Unit *back;
Lennart Poettering's avatar
Lennart Poettering committed
461
        int r;
462
463
464
465
466

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

467
        /* Fix backwards pointers */
Michal Schmidt's avatar
Michal Schmidt committed
468
        SET_FOREACH(back, other->dependencies[d], i) {
469
470
471
                UnitDependency k;

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

                                if (r == -EEXIST)
Michal Schmidt's avatar
Michal Schmidt committed
475
                                        set_remove(back->dependencies[k], other);
476
477
478
479
480
                                else
                                        assert(r == -ENOENT);
                        }
        }

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

Michal Schmidt's avatar
Michal Schmidt committed
483
484
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
485
486
487
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
488
489
490
491
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
492
493
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
494

495
496
        other = unit_follow_merge(other);

497
498
499
        if (other == u)
                return 0;

Michal Schmidt's avatar
Michal Schmidt committed
500
        if (u->type != other->type)
501
502
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
503
        if (!u->instance != !other->instance)
Lennart Poettering's avatar
Lennart Poettering committed
504
505
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
506
507
        if (other->load_state != UNIT_STUB &&
            other->load_state != UNIT_ERROR)
508
                return -EEXIST;
Lennart Poettering's avatar
Lennart Poettering committed
509

Michal Schmidt's avatar
Michal Schmidt committed
510
        if (other->job)
511
512
                return -EEXIST;

513
514
515
        if (other->nop_job)
                return -EEXIST;

516
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
517
518
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
519
        /* Merge names */
520
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
521

522
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
523
524
        while (other->refs)
                unit_ref_set(other->refs, u);
525

Lennart Poettering's avatar
Lennart Poettering committed
526
527
        /* Merge dependencies */
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
528
                merge_dependencies(u, other, d);
Lennart Poettering's avatar
Lennart Poettering committed
529

Michal Schmidt's avatar
Michal Schmidt committed
530
531
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
532

533
534
        /* 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
535
        if (other->load_state != UNIT_STUB)
536
537
538
539
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
540
541
542
543
544
545
546
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
547
548
        int r;
        char *s = NULL;
549
550
551
552

        assert(u);
        assert(name);

553
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
554
                if (!u->instance)
555
556
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
557
                if (!(s = unit_name_replace_instance(name, u->instance)))
558
559
560
561
562
                        return -ENOMEM;

                name = s;
        }

Michal Schmidt's avatar
Michal Schmidt committed
563
        if (!(other = manager_get_unit(u->manager, name)))
564
565
566
                r = unit_add_name(u, name);
        else
                r = unit_merge(u, other);
567

568
569
        free(s);
        return r;
570
571
572
573
574
}

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

Michal Schmidt's avatar
Michal Schmidt committed
575
576
        while (u->load_state == UNIT_MERGED)
                assert_se(u = u->merged_into);
577
578
579
580
581
582
583
584
585
586

        return u;
}

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

        assert(u);
        assert(c);

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

Lennart Poettering's avatar
Lennart Poettering committed
608
609
610
611
612
613
        return 0;
}

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

Michal Schmidt's avatar
Michal Schmidt committed
614
615
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
616

Michal Schmidt's avatar
Michal Schmidt committed
617
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
618
619
620
621
622
623
}

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

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
635
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
636
637
638

        if (!prefix)
                prefix = "";
639
640
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
641
642

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

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
680
        if (dual_timestamp_is_set(&u->condition_timestamp))
681
682
683
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
684
685
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
686

Lennart Poettering's avatar
Lennart Poettering committed
687
688
689
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
690
691
                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
692
693
        }

Michal Schmidt's avatar
Michal Schmidt committed
694
        if (u->load_state == UNIT_LOADED) {
695
696
697
                CGroupBonding *b;
                CGroupAttribute *a;

698
                fprintf(f,
699
                        "%s\tStopWhenUnneeded: %s\n"
700
701
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
702
                        "%s\tDefaultDependencies: %s\n"
703
                        "%s\tOnFailureIsolate: %s\n"
704
705
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
706
707
708
709
710
711
712
713
714
                        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)
715
716
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
717

Michal Schmidt's avatar
Michal Schmidt committed
718
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
719
720
721
722
723
                        char *v = NULL;

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

724
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
725
726
727
728
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
729

730
731
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
732

Michal Schmidt's avatar
Michal Schmidt committed
733
        } else if (u->load_state == UNIT_MERGED)
734
735
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
736
737
738
                        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));
739

Lennart Poettering's avatar
Lennart Poettering committed
740

Michal Schmidt's avatar
Michal Schmidt committed
741
742
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
743

744
745
746
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

747
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
748
749
750
}

/* Common implementation for multiple backends */
751
int unit_load_fragment_and_dropin(Unit *u) {
752
753
754
755
756
        int r;

        assert(u);

        /* Load a .service file */
757
        if ((r = unit_load_fragment(u)) < 0)
758
759
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
760
        if (u->load_state == UNIT_STUB)
761
762
763
764
765
766
767
768
769
770
                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 */
771
int unit_load_fragment_and_dropin_optional(Unit *u) {
772
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
773
774
775

        assert(u);

776
777
778
779
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
783
784
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
785

Lennart Poettering's avatar
Lennart Poettering committed
786
        /* Load drop-in directory data */
787
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
788
789
                return r;

790
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
791
792
}

793
int unit_add_default_target_dependency(Unit *u, Unit *target) {
794
795
796
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
797
        if (target->type != UNIT_TARGET)
798
799
                return 0;

Harald Hoyer's avatar
Harald Hoyer committed
800
        /* Only add the dependency if both units are loaded, so that
801
         * that loop check below is reliable */
Michal Schmidt's avatar
Michal Schmidt committed
802
803
        if (u->load_state != UNIT_LOADED ||
            target->load_state != UNIT_LOADED)
804
805
                return 0;

806
807
        /* If either side wants no automatic dependencies, then let's
         * skip this */
Michal Schmidt's avatar
Michal Schmidt committed
808
809
        if (!u->default_dependencies ||
            !target->default_dependencies)
810
811
                return 0;

812
        /* Don't create loops */
Michal Schmidt's avatar
Michal Schmidt committed
813
        if (set_get(target->dependencies[UNIT_BEFORE], u))
814
815
816
817
818
819
                return 0;

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

static int unit_add_default_dependencies(Unit *u) {
820
821
822
823
824
825
826
        static const UnitDependency deps[] = {
                UNIT_REQUIRED_BY,
                UNIT_REQUIRED_BY_OVERRIDABLE,
                UNIT_WANTED_BY,
                UNIT_BOUND_BY
        };

827
        Unit *target;
828
829
        Iterator i;
        int r;
830
        unsigned k;
831
832
833

        assert(u);

834
        for (k = 0; k < ELEMENTSOF(deps); k++)
Michal Schmidt's avatar
Michal Schmidt committed
835
                SET_FOREACH(target, u->dependencies[deps[k]], i)
836
837
                        if ((r = unit_add_default_target_dependency(u, target)) < 0)
                                return r;
838

839
840
841
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
842
843
844
845
846
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
847
848
849
        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
850
851
        }

Michal Schmidt's avatar
Michal Schmidt committed
852
        if (u->type == _UNIT_TYPE_INVALID)
853
854
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
855
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
856
857
                return 0;

858
859
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
860
                        goto fail;
861

Michal Schmidt's avatar
Michal Schmidt committed
862
        if (u->load_state == UNIT_STUB) {
863
864
865
866
                r = -ENOENT;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
867
868
        if (u->load_state == UNIT_LOADED &&
            u->default_dependencies)
869
870
871
                if ((r = unit_add_default_dependencies(u)) < 0)
                        goto fail;

Michal Schmidt's avatar
Michal Schmidt committed
872
873
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
874
875

                log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
Michal Schmidt's avatar
Michal Schmidt committed
876
                          u->id);
877
878
879
880
881

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
882
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
883
884

        unit_add_to_dbus_queue(unit_follow_merge(u));
885
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
886
887
888
889

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
890
891
        u->load_state = UNIT_ERROR;
        u->load_error = r;
892
        unit_add_to_dbus_queue(u);
893
        unit_add_to_gc_queue(u);
894

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

Lennart Poettering's avatar
Lennart Poettering committed
897
898
899
        return r;
}

900
901
902
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
903
904
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
905

Michal Schmidt's avatar
Michal Schmidt committed
906
        return u->condition_result;
907
908
}

Lennart Poettering's avatar
Lennart Poettering committed
909
/* Errors:
910
911
912
913
 *         -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
914
915
916
 */
int unit_start(Unit *u) {
        UnitActiveState state;
917
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
918
919
920

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
921
        if (u->load_state != UNIT_LOADED)
922
923
                return -EINVAL;

924
925
926
927
        /* 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
928
929
930
931
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

932
933
934
935
936
937
        /* 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
938
                log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);
939
940
941
                return -EALREADY;
        }

942
943
        /* Forward to the main object, if we aren't it. */
        if ((following = unit_following(u))) {
Michal Schmidt's avatar
Michal Schmidt committed
944
                log_debug("Redirecting start request from %s to %s.", u->id, following->id);
945
946
947
948
949
950
951
                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
952
953
954
955
956
957
        /* 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. */

958
        unit_add_to_dbus_queue(u);
959

960
        unit_status_printf(u, NULL, "Starting %s...", unit_description(u));
Lennart Poettering's avatar
Lennart Poettering committed
961
962
963
964
965
966
967
968
969
        return UNIT_VTABLE(u)->start(u);
}

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

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

970
971
972
973
bool unit_can_isolate(Unit *u) {
        assert(u);

        return unit_can_start(u) &&
Michal Schmidt's avatar
Michal Schmidt committed
974
                u->allow_isolate;
975
976
}

Lennart Poettering's avatar
Lennart Poettering committed
977