]> git.proxmox.com Git - systemd.git/blame - src/core/unit.h
Imported Upstream version 208
[systemd.git] / src / core / unit.h
CommitLineData
663996b3
MS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3#pragma once
4
5/***
6 This file is part of systemd.
7
8 Copyright 2010 Lennart Poettering
9
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22***/
23
24#include <stdbool.h>
25#include <stdlib.h>
26#include <unistd.h>
27
28typedef struct Unit Unit;
29typedef struct UnitVTable UnitVTable;
30typedef enum UnitActiveState UnitActiveState;
31typedef enum UnitDependency UnitDependency;
32typedef struct UnitRef UnitRef;
33typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
34
35#include "set.h"
36#include "util.h"
37#include "list.h"
38#include "socket-util.h"
39#include "execute.h"
14228c0d 40#include "cgroup.h"
663996b3
MS
41#include "condition.h"
42#include "install.h"
43#include "unit-name.h"
663996b3
MS
44
45enum UnitActiveState {
46 UNIT_ACTIVE,
47 UNIT_RELOADING,
48 UNIT_INACTIVE,
49 UNIT_FAILED,
50 UNIT_ACTIVATING,
51 UNIT_DEACTIVATING,
52 _UNIT_ACTIVE_STATE_MAX,
53 _UNIT_ACTIVE_STATE_INVALID = -1
54};
55
56static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
57 return t == UNIT_ACTIVE || t == UNIT_RELOADING;
58}
59
60static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) {
61 return t == UNIT_ACTIVE || t == UNIT_ACTIVATING || t == UNIT_RELOADING;
62}
63
64static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) {
65 return t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_DEACTIVATING;
66}
67
68static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
69 return t == UNIT_INACTIVE || t == UNIT_FAILED;
70}
71
72enum UnitDependency {
73 /* Positive dependencies */
74 UNIT_REQUIRES,
75 UNIT_REQUIRES_OVERRIDABLE,
76 UNIT_REQUISITE,
77 UNIT_REQUISITE_OVERRIDABLE,
78 UNIT_WANTS,
79 UNIT_BINDS_TO,
80 UNIT_PART_OF,
81
82 /* Inverse of the above */
83 UNIT_REQUIRED_BY, /* inverse of 'requires' and 'requisite' is 'required_by' */
84 UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' and 'requisite_overridable' is 'soft_required_by' */
85 UNIT_WANTED_BY, /* inverse of 'wants' */
86 UNIT_BOUND_BY, /* inverse of 'binds_to' */
87 UNIT_CONSISTS_OF, /* inverse of 'part_of' */
88
89 /* Negative dependencies */
90 UNIT_CONFLICTS, /* inverse of 'conflicts' is 'conflicted_by' */
91 UNIT_CONFLICTED_BY,
92
93 /* Order */
94 UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */
95 UNIT_AFTER,
96
97 /* On Failure */
98 UNIT_ON_FAILURE,
99
100 /* Triggers (i.e. a socket triggers a service) */
101 UNIT_TRIGGERS,
102 UNIT_TRIGGERED_BY,
103
104 /* Propagate reloads */
105 UNIT_PROPAGATES_RELOAD_TO,
106 UNIT_RELOAD_PROPAGATED_FROM,
107
108 /* Reference information for GC logic */
109 UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
110 UNIT_REFERENCED_BY,
111
112 _UNIT_DEPENDENCY_MAX,
113 _UNIT_DEPENDENCY_INVALID = -1
114};
115
116#include "manager.h"
117#include "job.h"
14228c0d
MB
118
119struct UnitRef {
120 /* Keeps tracks of references to a unit. This is useful so
121 * that we can merge two units if necessary and correct all
122 * references to them */
123
124 Unit* unit;
125 LIST_FIELDS(UnitRef, refs);
126};
663996b3
MS
127
128struct Unit {
129 Manager *manager;
130
131 UnitType type;
132 UnitLoadState load_state;
133 Unit *merged_into;
134
135 char *id; /* One name is special because we use it for identification. Points to an entry in the names set */
136 char *instance;
137
138 Set *names;
139 Set *dependencies[_UNIT_DEPENDENCY_MAX];
140
141 char **requires_mounts_for;
142
143 char *description;
144 char **documentation;
145
146 char *fragment_path; /* if loaded from a config file this is the primary path to it */
147 char *source_path; /* if converted, the source file */
148 char **dropin_paths;
149 usec_t fragment_mtime;
150 usec_t source_mtime;
151 usec_t dropin_mtime;
152
153 /* If there is something to do with this unit, then this is the installed job for it */
154 Job *job;
155
156 /* JOB_NOP jobs are special and can be installed without disturbing the real job. */
157 Job *nop_job;
158
159 usec_t job_timeout;
160
161 /* References to this */
162 LIST_HEAD(UnitRef, refs);
163
164 /* Conditions to check */
165 LIST_HEAD(Condition, conditions);
166
167 dual_timestamp condition_timestamp;
168
169 dual_timestamp inactive_exit_timestamp;
170 dual_timestamp active_enter_timestamp;
171 dual_timestamp active_exit_timestamp;
172 dual_timestamp inactive_enter_timestamp;
173
174 /* Counterparts in the cgroup filesystem */
14228c0d
MB
175 char *cgroup_path;
176 CGroupControllerMask cgroup_mask;
177
178 UnitRef slice;
663996b3
MS
179
180 /* Per type list */
181 LIST_FIELDS(Unit, units_by_type);
182
183 /* All units which have requires_mounts_for set */
184 LIST_FIELDS(Unit, has_requires_mounts_for);
185
186 /* Load queue */
187 LIST_FIELDS(Unit, load_queue);
188
189 /* D-Bus queue */
190 LIST_FIELDS(Unit, dbus_queue);
191
192 /* Cleanup queue */
193 LIST_FIELDS(Unit, cleanup_queue);
194
195 /* GC queue */
196 LIST_FIELDS(Unit, gc_queue);
197
14228c0d
MB
198 /* CGroup realize members queue */
199 LIST_FIELDS(Unit, cgroup_queue);
200
663996b3
MS
201 /* Used during GC sweeps */
202 unsigned gc_marker;
203
204 /* When deserializing, temporarily store the job type for this
205 * unit here, if there was a job scheduled.
206 * Only for deserializing from a legacy version. New style uses full
207 * serialized jobs. */
208 int deserialized_job; /* This is actually of type JobType */
209
210 /* Error code when we didn't manage to load the unit (negative) */
211 int load_error;
212
213 /* Cached unit file state */
214 UnitFileState unit_file_state;
215
216 /* Garbage collect us we nobody wants or requires us anymore */
217 bool stop_when_unneeded;
218
219 /* Create default dependencies */
220 bool default_dependencies;
221
222 /* Refuse manual starting, allow starting only indirectly via dependency. */
223 bool refuse_manual_start;
224
225 /* Don't allow the user to stop this unit manually, allow stopping only indirectly via dependency. */
226 bool refuse_manual_stop;
227
228 /* Allow isolation requests */
229 bool allow_isolate;
230
231 /* Isolate OnFailure unit */
232 bool on_failure_isolate;
233
234 /* Ignore this unit when isolating */
235 bool ignore_on_isolate;
236
237 /* Ignore this unit when snapshotting */
238 bool ignore_on_snapshot;
239
240 /* Did the last condition check succeed? */
241 bool condition_result;
242
14228c0d
MB
243 /* Is this a transient unit? */
244 bool transient;
245
663996b3
MS
246 bool in_load_queue:1;
247 bool in_dbus_queue:1;
248 bool in_cleanup_queue:1;
249 bool in_gc_queue:1;
14228c0d 250 bool in_cgroup_queue:1;
663996b3
MS
251
252 bool sent_dbus_new_signal:1;
253
254 bool no_gc:1;
255
256 bool in_audit:1;
663996b3 257
14228c0d 258 bool cgroup_realized:1;
663996b3
MS
259};
260
261struct UnitStatusMessageFormats {
262 const char *starting_stopping[2];
263 const char *finished_start_job[_JOB_RESULT_MAX];
264 const char *finished_stop_job[_JOB_RESULT_MAX];
265};
266
14228c0d
MB
267typedef enum UnitSetPropertiesMode {
268 UNIT_CHECK = 0,
269 UNIT_RUNTIME = 1,
270 UNIT_PERSISTENT = 2,
271} UnitSetPropertiesMode;
272
663996b3
MS
273#include "service.h"
274#include "timer.h"
275#include "socket.h"
276#include "target.h"
277#include "device.h"
278#include "mount.h"
279#include "automount.h"
280#include "snapshot.h"
281#include "swap.h"
282#include "path.h"
14228c0d
MB
283#include "slice.h"
284#include "scope.h"
663996b3
MS
285
286struct UnitVTable {
287 /* How much memory does an object of this unit type need */
288 size_t object_size;
289
290 /* If greater than 0, the offset into the object where
291 * ExecContext is found, if the unit type has that */
292 size_t exec_context_offset;
293
14228c0d
MB
294 /* If greater than 0, the offset into the object where
295 * CGroupContext is found, if the unit type has that */
296 size_t cgroup_context_offset;
297
298 /* The name of the configuration file section with the private settings of this unit*/
299 const char *private_section;
663996b3
MS
300
301 /* Config file sections this unit type understands, separated
302 * by NUL chars */
303 const char *sections;
304
305 /* This should reset all type-specific variables. This should
306 * not allocate memory, and is called with zero-initialized
307 * data. It should hence only initialize variables that need
308 * to be set != 0. */
309 void (*init)(Unit *u);
310
311 /* This should free all type-specific variables. It should be
312 * idempotent. */
313 void (*done)(Unit *u);
314
315 /* Actually load data from disk. This may fail, and should set
316 * load_state to UNIT_LOADED, UNIT_MERGED or leave it at
317 * UNIT_STUB if no configuration could be found. */
318 int (*load)(Unit *u);
319
320 /* If a lot of units got created via enumerate(), this is
321 * where to actually set the state and call unit_notify(). */
322 int (*coldplug)(Unit *u);
323
324 void (*dump)(Unit *u, FILE *f, const char *prefix);
325
326 int (*start)(Unit *u);
327 int (*stop)(Unit *u);
328 int (*reload)(Unit *u);
329
330 int (*kill)(Unit *u, KillWho w, int signo, DBusError *error);
331
332 bool (*can_reload)(Unit *u);
333
334 /* Write all data that cannot be restored from other sources
335 * away using unit_serialize_item() */
336 int (*serialize)(Unit *u, FILE *f, FDSet *fds);
337
338 /* Restore one item from the serialization */
339 int (*deserialize_item)(Unit *u, const char *key, const char *data, FDSet *fds);
340
341 /* Try to match up fds with what we need for this unit */
342 int (*distribute_fds)(Unit *u, FDSet *fds);
343
344 /* Boils down the more complex internal state of this unit to
345 * a simpler one that the engine can understand */
346 UnitActiveState (*active_state)(Unit *u);
347
348 /* Returns the substate specific to this unit type as
349 * string. This is purely information so that we can give the
350 * user a more fine grained explanation in which actual state a
351 * unit is in. */
352 const char* (*sub_state_to_string)(Unit *u);
353
354 /* Return true when there is reason to keep this entry around
355 * even nothing references it and it isn't active in any
356 * way */
357 bool (*check_gc)(Unit *u);
358
359 /* Return true when this unit is suitable for snapshotting */
360 bool (*check_snapshot)(Unit *u);
361
362 void (*fd_event)(Unit *u, int fd, uint32_t events, Watch *w);
363 void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
364 void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
365
366 /* Reset failed state if we are in failed state */
367 void (*reset_failed)(Unit *u);
368
369 /* Called whenever any of the cgroups this unit watches for
370 * ran empty */
14228c0d 371 void (*notify_cgroup_empty)(Unit *u);
663996b3
MS
372
373 /* Called whenever a process of this unit sends us a message */
374 void (*notify_message)(Unit *u, pid_t pid, char **tags);
375
376 /* Called whenever a name this Unit registered for comes or
377 * goes away. */
378 void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
379
380 /* Called whenever a bus PID lookup finishes */
381 void (*bus_query_pid_done)(Unit *u, const char *name, pid_t pid);
382
383 /* Called for each message received on the bus */
384 DBusHandlerResult (*bus_message_handler)(Unit *u, DBusConnection *c, DBusMessage *message);
385
14228c0d
MB
386 /* Called for each property that is being set */
387 int (*bus_set_property)(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
388
389 /* Called after at least one property got changed to apply the necessary change */
390 int (*bus_commit_properties)(Unit *u);
391
663996b3
MS
392 /* Return the unit this unit is following */
393 Unit *(*following)(Unit *u);
394
395 /* Return the set of units that are following each other */
396 int (*following_set)(Unit *u, Set **s);
397
398 /* Invoked each time a unit this unit is triggering changes
399 * state or gains/loses a job */
400 void (*trigger_notify)(Unit *u, Unit *trigger);
401
402 /* Called whenever CLOCK_REALTIME made a jump */
403 void (*time_change)(Unit *u);
404
405 /* This is called for each unit type and should be used to
406 * enumerate existing devices and load them. However,
407 * everything that is loaded here should still stay in
408 * inactive state. It is the job of the coldplug() call above
409 * to put the units into the initial state. */
410 int (*enumerate)(Manager *m);
411
412 /* Type specific cleanups. */
413 void (*shutdown)(Manager *m);
414
415 /* When sending out PropertiesChanged signal, which properties
416 * shall be invalidated? This is a NUL separated list of
417 * strings, to minimize relocations a little. */
418 const char *bus_invalidating_properties;
419
420 /* The interface name */
421 const char *bus_interface;
422
423 UnitStatusMessageFormats status_message_formats;
424
425 /* Can units of this type have multiple names? */
426 bool no_alias:1;
427
428 /* Instances make no sense for this type */
429 bool no_instances:1;
430
431 /* Exclude from automatic gc */
432 bool no_gc:1;
14228c0d
MB
433
434 /* True if transient units of this type are OK */
435 bool can_transient:1;
663996b3
MS
436};
437
438extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
439
440#define UNIT_VTABLE(u) unit_vtable[(u)->type]
441
442/* For casting a unit into the various unit types */
443#define DEFINE_CAST(UPPERCASE, MixedCase) \
444 static inline MixedCase* UPPERCASE(Unit *u) { \
445 if (_unlikely_(!u || u->type != UNIT_##UPPERCASE)) \
446 return NULL; \
447 \
448 return (MixedCase*) u; \
449 }
450
451/* For casting the various unit types into a unit */
452#define UNIT(u) (&(u)->meta)
453
454#define UNIT_TRIGGER(u) ((Unit*) set_first((u)->dependencies[UNIT_TRIGGERS]))
455
456DEFINE_CAST(SOCKET, Socket);
457DEFINE_CAST(TIMER, Timer);
458DEFINE_CAST(SERVICE, Service);
459DEFINE_CAST(TARGET, Target);
460DEFINE_CAST(DEVICE, Device);
461DEFINE_CAST(MOUNT, Mount);
462DEFINE_CAST(AUTOMOUNT, Automount);
463DEFINE_CAST(SNAPSHOT, Snapshot);
464DEFINE_CAST(SWAP, Swap);
465DEFINE_CAST(PATH, Path);
14228c0d
MB
466DEFINE_CAST(SLICE, Slice);
467DEFINE_CAST(SCOPE, Scope);
663996b3
MS
468
469Unit *unit_new(Manager *m, size_t size);
470void unit_free(Unit *u);
471
472int unit_add_name(Unit *u, const char *name);
473
474int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference);
475int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference);
476
477int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *filename, bool add_reference);
478int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference);
479
480int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *filename, bool add_reference);
481int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference);
482
483int unit_add_exec_dependencies(Unit *u, ExecContext *c);
484
663996b3
MS
485int unit_choose_id(Unit *u, const char *name);
486int unit_set_description(Unit *u, const char *description);
487
488bool unit_check_gc(Unit *u);
489
490void unit_add_to_load_queue(Unit *u);
491void unit_add_to_dbus_queue(Unit *u);
492void unit_add_to_cleanup_queue(Unit *u);
493void unit_add_to_gc_queue(Unit *u);
494
495int unit_merge(Unit *u, Unit *other);
496int unit_merge_by_name(Unit *u, const char *other);
497
498Unit *unit_follow_merge(Unit *u) _pure_;
499
500int unit_load_fragment_and_dropin(Unit *u);
501int unit_load_fragment_and_dropin_optional(Unit *u);
502int unit_load(Unit *unit);
503
14228c0d
MB
504int unit_add_default_slice(Unit *u);
505
663996b3
MS
506const char *unit_description(Unit *u) _pure_;
507
508bool unit_has_name(Unit *u, const char *name);
509
510UnitActiveState unit_active_state(Unit *u);
511
512const char* unit_sub_state_to_string(Unit *u);
513
514void unit_dump(Unit *u, FILE *f, const char *prefix);
515
516bool unit_can_reload(Unit *u) _pure_;
517bool unit_can_start(Unit *u) _pure_;
518bool unit_can_isolate(Unit *u) _pure_;
519
520int unit_start(Unit *u);
521int unit_stop(Unit *u);
522int unit_reload(Unit *u);
523
524int unit_kill(Unit *u, KillWho w, int signo, DBusError *error);
525int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, DBusError *error);
526
527void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
528
529int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w);
530void unit_unwatch_fd(Unit *u, Watch *w);
531
532int unit_watch_pid(Unit *u, pid_t pid);
533void unit_unwatch_pid(Unit *u, pid_t pid);
534
535int unit_watch_timer(Unit *u, clockid_t, bool relative, usec_t usec, Watch *w);
536void unit_unwatch_timer(Unit *u, Watch *w);
537
538int unit_watch_bus_name(Unit *u, const char *name);
539void unit_unwatch_bus_name(Unit *u, const char *name);
540
541bool unit_job_is_applicable(Unit *u, JobType j);
542
543int set_unit_path(const char *p);
544
545char *unit_dbus_path(Unit *u);
546
547int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
548int unit_get_related_unit(Unit *u, const char *type, Unit **_found);
549
550bool unit_can_serialize(Unit *u) _pure_;
551int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
552void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_attr_(4,5);
553void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
554int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
555
556int unit_add_node_link(Unit *u, const char *what, bool wants);
557
558int unit_coldplug(Unit *u);
559
560void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_attr_(3, 0);
561
562bool unit_need_daemon_reload(Unit *u);
563
564void unit_reset_failed(Unit *u);
565
566Unit *unit_following(Unit *u);
567
14228c0d
MB
568const char *unit_slice_name(Unit *u);
569
663996b3
MS
570bool unit_stop_pending(Unit *u) _pure_;
571bool unit_inactive_or_pending(Unit *u) _pure_;
572bool unit_active_or_pending(Unit *u);
573
574int unit_add_default_target_dependency(Unit *u, Unit *target);
575
576char *unit_default_cgroup_path(Unit *u);
577
578int unit_following_set(Unit *u, Set **s);
579
580void unit_start_on_failure(Unit *u);
581void unit_trigger_notify(Unit *u);
582
583bool unit_condition_test(Unit *u);
584
585UnitFileState unit_get_unit_file_state(Unit *u);
586
587Unit* unit_ref_set(UnitRef *ref, Unit *u);
588void unit_ref_unset(UnitRef *ref);
589
590#define UNIT_DEREF(ref) ((ref).unit)
14228c0d 591#define UNIT_ISSET(ref) (!!(ref).unit)
663996b3 592
663996b3
MS
593int unit_add_mount_links(Unit *u);
594
595int unit_exec_context_defaults(Unit *u, ExecContext *c);
596
597ExecContext *unit_get_exec_context(Unit *u) _pure_;
14228c0d 598CGroupContext *unit_get_cgroup_context(Unit *u) _pure_;
663996b3 599
14228c0d
MB
600int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
601int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_attr_(4,5);
602
603int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
604int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_attr_(4,5);
605
606int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name);
663996b3
MS
607
608int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid_t control_pid, bool main_pid_alien);
609
14228c0d
MB
610int unit_make_transient(Unit *u);
611
612int unit_require_mounts_for(Unit *u, const char *path);
613
663996b3
MS
614const char *unit_active_state_to_string(UnitActiveState i) _const_;
615UnitActiveState unit_active_state_from_string(const char *s) _pure_;
616
617const char *unit_dependency_to_string(UnitDependency i) _const_;
618UnitDependency unit_dependency_from_string(const char *s) _pure_;
619
620/* Macros which append UNIT= or USER_UNIT= to the message */
621
622#define log_full_unit(level, unit, ...) log_meta_object(level, __FILE__, __LINE__, __func__, getpid() == 1 ? "UNIT=" : "USER_UNIT=", unit, __VA_ARGS__)
623#define log_debug_unit(unit, ...) log_full_unit(LOG_DEBUG, unit, __VA_ARGS__)
624#define log_info_unit(unit, ...) log_full_unit(LOG_INFO, unit, __VA_ARGS__)
625#define log_notice_unit(unit, ...) log_full_unit(LOG_NOTICE, unit, __VA_ARGS__)
626#define log_warning_unit(unit, ...) log_full_unit(LOG_WARNING, unit, __VA_ARGS__)
627#define log_error_unit(unit, ...) log_full_unit(LOG_ERR, unit, __VA_ARGS__)
628
629#define log_struct_unit(level, unit, ...) log_struct(level, getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit, __VA_ARGS__)