• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 15199265962

22 May 2025 09:40PM UTC coverage: 72.061% (-0.02%) from 72.079%
15199265962

push

github

bluca
tests: fix TEST-74-AUX-UTILS.varlinkctl.sh (#37562)

per Daan's explanation:
other subtests running as testuser apparently use systemd-run --user
--machine testuser@.host which turns user tracking in logind into "by
pin" mode. when the last pinning session exits it terminates the user.

299156 of 415145 relevant lines covered (72.06%)

703915.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

7.69
/src/systemctl/systemctl-sysv-compat.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <fcntl.h>
4
#include <stdlib.h>
5

6
#include "env-util.h"
7
#include "fd-util.h"
8
#include "initreq.h"
9
#include "install.h"
10
#include "io-util.h"
11
#include "log.h"
12
#include "parse-util.h"
13
#include "path-lookup.h"
14
#include "path-util.h"
15
#include "process-util.h"
16
#include "string-util.h"
17
#include "strv.h"
18
#include "systemctl.h"
19
#include "systemctl-sysv-compat.h"
20
#include "time-util.h"
21

22
int talk_initctl(char rl) {
×
23
#if HAVE_SYSV_COMPAT
24
        _cleanup_close_ int fd = -EBADF;
25
        const char *path;
26
        int r;
27

28
        /* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this
29
         * system, and > 0 on success. */
30

31
        if (rl == 0)
32
                return 0;
33

34
        FOREACH_STRING(_path, "/run/initctl", "/dev/initctl") {
35
                path = _path;
36

37
                fd = open(path, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
38
                if (fd < 0 && errno != ENOENT)
39
                        return log_error_errno(errno, "Failed to open %s: %m", path);
40
                if (fd >= 0)
41
                        break;
42
        }
43
        if (fd < 0)
44
                return 0;
45

46
        struct init_request request = {
47
                .magic = INIT_MAGIC,
48
                .sleeptime = 0,
49
                .cmd = INIT_CMD_RUNLVL,
50
                .runlevel = rl,
51
        };
52

53
        r = loop_write(fd, &request, sizeof(request));
54
        if (r < 0)
55
                return log_error_errno(r, "Failed to write to %s: %m", path);
56

57
        return 1;
58
#else
59
        return -EOPNOTSUPP;
×
60
#endif
61
}
62

63
int parse_shutdown_time_spec(const char *t, usec_t *ret) {
×
64
        int r;
×
65

66
        assert(t);
×
67
        assert(ret);
×
68

69
        if (streq(t, "now"))
×
70
                *ret = 0;
×
71
        else if (!strchr(t, ':')) {
×
72
                uint64_t u;
×
73

74
                if (safe_atou64(t, &u) < 0)
×
75
                        return -EINVAL;
×
76

77
                *ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
×
78
        } else {
79
                char *e = NULL;
×
80
                long hour, minute;
×
81

82
                errno = 0;
×
83
                hour = strtol(t, &e, 10);
×
84
                if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
×
85
                        return -EINVAL;
×
86

87
                minute = strtol(e+1, &e, 10);
×
88
                if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
×
89
                        return -EINVAL;
90

91
                usec_t n = now(CLOCK_REALTIME);
×
92
                struct tm tm = {};
×
93

94
                r = localtime_or_gmtime_usec(n, /* utc= */ false, &tm);
×
95
                if (r < 0)
×
96
                        return r;
97

98
                tm.tm_hour = (int) hour;
×
99
                tm.tm_min = (int) minute;
×
100
                tm.tm_sec = 0;
×
101

102
                usec_t s;
×
103
                r = mktime_or_timegm_usec(&tm, /* utc= */ false, &s);
×
104
                if (r < 0)
×
105
                        return r;
106

107
                while (s <= n)
×
108
                        s += USEC_PER_DAY;
×
109

110
                *ret = s;
×
111
        }
112

113
        return 0;
114
}
115

116
int enable_sysv_units(const char *verb, char **args) {
479✔
117
        int r = 0;
479✔
118

119
#if HAVE_SYSV_COMPAT
120
        _cleanup_(lookup_paths_done) LookupPaths paths = {};
121
        unsigned f = 0;
122
        SysVUnitEnableState enable_state = SYSV_UNIT_NOT_FOUND;
123

124
        /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
125

126
        if (arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
127
                return 0;
128

129
        if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
130
                return 0;
131

132
        if (!STR_IN_SET(verb,
133
                        "enable",
134
                        "disable",
135
                        "is-enabled"))
136
                return 0;
137

138
        r = lookup_paths_init_or_warn(&paths, arg_runtime_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root);
139
        if (r < 0)
140
                return r;
141

142
        r = 0;
143
        while (args[f]) {
144

145
                const char *argv[] = {
146
                        LIBEXECDIR "/systemd-sysv-install",
147
                        NULL, /* --root= */
148
                        NULL, /* verb */
149
                        NULL, /* service */
150
                        NULL,
151
                };
152

153
                _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL, *v = NULL;
154
                bool found_native = false, found_sysv;
155
                const char *name;
156
                unsigned c = 1;
157
                pid_t pid;
158
                int j;
159

160
                name = args[f++];
161

162
                if (!endswith(name, ".service"))
163
                        continue;
164

165
                if (path_is_absolute(name))
166
                        continue;
167

168
                j = unit_file_exists(arg_runtime_scope, &paths, name);
169
                if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
170
                        return log_error_errno(j, "Failed to look up unit file state: %m");
171
                found_native = j != 0;
172

173
                /* If we have both a native unit and a SysV script, enable/disable them both (below); for
174
                 * is-enabled, prefer the native unit */
175
                if (found_native && streq(verb, "is-enabled"))
176
                        continue;
177

178
                p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
179
                if (!p)
180
                        return log_oom();
181

182
                p[strlen(p) - STRLEN(".service")] = 0;
183
                found_sysv = access(p, F_OK) >= 0;
184
                if (!found_sysv)
185
                        continue;
186

187
                if (!arg_quiet) {
188
                        if (found_native)
189
                                log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
190
                        else
191
                                log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
192
                }
193

194
                if (!isempty(arg_root)) {
195
                        q = strjoin("--root=", arg_root);
196
                        if (!q)
197
                                return log_oom();
198

199
                        argv[c++] = q;
200
                }
201

202
                /* Let's copy the verb, since it's still pointing directly into the original argv[] array we
203
                 * got passed, but safe_fork() is likely going to rewrite that for the new child */
204
                v = strdup(verb);
205
                if (!v)
206
                        return log_oom();
207

208
                argv[c++] = v;
209
                argv[c++] = basename(p);
210
                argv[c] = NULL;
211

212
                l = strv_join((char**)argv, " ");
213
                if (!l)
214
                        return log_oom();
215

216
                if (!arg_quiet)
217
                        log_info("Executing: %s", l);
218

219
                j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
220
                if (j < 0)
221
                        return j;
222
                if (j == 0) {
223
                        /* Child */
224
                        execv(argv[0], (char**) argv);
225
                        log_error_errno(errno, "Failed to execute %s: %m", argv[0]);
226
                        _exit(EXIT_FAILURE);
227
                }
228

229
                j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
230
                if (j < 0)
231
                        return j;
232
                if (streq(verb, "is-enabled")) {
233
                        if (j == EXIT_SUCCESS) {
234
                                if (!arg_quiet)
235
                                        puts("enabled");
236
                                enable_state = SYSV_UNIT_ENABLED;
237
                        } else {
238
                                if (!arg_quiet)
239
                                        puts("disabled");
240
                                if (enable_state != SYSV_UNIT_ENABLED)
241
                                        enable_state = SYSV_UNIT_DISABLED;
242
                        }
243

244
                } else if (j != EXIT_SUCCESS)
245
                        return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
246

247
                if (found_native)
248
                        continue;
249

250
                /* Remove this entry, so that we don't try enabling it as native unit */
251
                assert(f > 0);
252
                f--;
253
                assert(args[f] == name);
254
                strv_remove(args + f, name);
255
        }
256

257
        if (streq(verb, "is-enabled"))
258
                return enable_state;
259
#endif
260
        return r;
479✔
261
}
262

263
int action_to_runlevel(void) {
×
264
#if HAVE_SYSV_COMPAT
265
        static const char table[_ACTION_MAX] = {
266
                [ACTION_HALT] =      '0',
267
                [ACTION_POWEROFF] =  '0',
268
                [ACTION_REBOOT] =    '6',
269
                [ACTION_RUNLEVEL2] = '2',
270
                [ACTION_RUNLEVEL3] = '3',
271
                [ACTION_RUNLEVEL4] = '4',
272
                [ACTION_RUNLEVEL5] = '5',
273
                [ACTION_RESCUE] =    '1'
274
        };
275

276
        assert(arg_action >= 0 && arg_action < _ACTION_MAX);
277
        return table[arg_action];
278
#else
279
        return -EOPNOTSUPP;
×
280
#endif
281
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc