]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/util.c
util-lib: move is_main_thread() to process-util.[ch]
[thirdparty/systemd.git] / src / basic / util.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
f6c2284a
LP
22#include <ctype.h>
23#include <dirent.h>
60918275 24#include <errno.h>
f6c2284a
LP
25#include <fcntl.h>
26#include <glob.h>
27#include <grp.h>
28#include <langinfo.h>
20f56fdd 29#include <libintl.h>
f6c2284a
LP
30#include <limits.h>
31#include <linux/magic.h>
257b0719 32#include <linux/oom.h>
ef886c6a 33#include <linux/sched.h>
f6c2284a 34#include <locale.h>
0a6f50c0 35#include <poll.h>
ef2f1067 36#include <pwd.h>
f6c2284a
LP
37#include <sched.h>
38#include <signal.h>
39#include <stdarg.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sys/file.h>
44#include <sys/ioctl.h>
87d2c1ff 45#include <sys/mman.h>
6d313367 46#include <sys/mount.h>
6afc95b7 47#include <sys/personality.h>
f6c2284a 48#include <sys/prctl.h>
f6c2284a 49#include <sys/stat.h>
abe4aa14 50#include <sys/statvfs.h>
f6c2284a
LP
51#include <sys/time.h>
52#include <sys/types.h>
53#include <sys/utsname.h>
54#include <sys/vfs.h>
55#include <sys/wait.h>
f6c2284a
LP
56#include <syslog.h>
57#include <unistd.h>
eef46c37
LP
58
59/* When we include libgen.h because we need dirname() we immediately
f6c2284a
LP
60 * undefine basename() since libgen.h defines it as a macro to the
61 * POSIX version which is really broken. We prefer GNU basename(). */
eef46c37 62#include <libgen.h>
2b6bf07d 63#undef basename
60918275 64
9bf3b535
LP
65#ifdef HAVE_SYS_AUXV_H
66#include <sys/auxv.h>
67#endif
68
f6c2284a
LP
69/* We include linux/fs.h as last of the system headers, as it
70 * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
71#include <linux/fs.h>
72
3f6fd1ba 73#include "build.h"
f6c2284a
LP
74#include "def.h"
75#include "device-nodes.h"
76#include "env-util.h"
4f5dd394 77#include "escape.h"
f6c2284a 78#include "exit-status.h"
3ffd4af2 79#include "fd-util.h"
f6c2284a
LP
80#include "fileio.h"
81#include "formats-util.h"
82#include "gunicode.h"
83#include "hashmap.h"
84#include "hostname-util.h"
1dccbe19 85#include "ioprio.h"
a9f5d454 86#include "log.h"
f6c2284a
LP
87#include "macro.h"
88#include "missing.h"
c38dfac9 89#include "mkdir.h"
e4e73a63 90#include "hexdecoct.h"
6bedfcbb 91#include "parse-util.h"
9eb977db 92#include "path-util.h"
0b452006 93#include "process-util.h"
3df3e884 94#include "random-util.h"
24882e06 95#include "signal-util.h"
f6c2284a 96#include "sparse-endian.h"
8b43440b 97#include "string-table.h"
07630cea 98#include "string-util.h"
f6c2284a
LP
99#include "strv.h"
100#include "terminal-util.h"
b1d4f8e1 101#include "user-util.h"
f6c2284a 102#include "utf8.h"
4f5dd394 103#include "util.h"
3ffd4af2 104#include "virt.h"
a0956174 105#include "dirent-util.h"
8fcde012 106#include "stat-util.h"
56cf987f 107
012d7b42
ZJS
108/* Put this test here for a lack of better place */
109assert_cc(EAGAIN == EWOULDBLOCK);
110
9a0e6896
LP
111int saved_argc = 0;
112char **saved_argv = NULL;
9086e840 113
37f85e66 114size_t page_size(void) {
ec202eae 115 static thread_local size_t pgsz = 0;
37f85e66 116 long r;
117
87d2c1ff 118 if (_likely_(pgsz > 0))
37f85e66 119 return pgsz;
120
e67f47e5
LP
121 r = sysconf(_SC_PAGESIZE);
122 assert(r > 0);
37f85e66 123
124 pgsz = (size_t) r;
37f85e66 125 return pgsz;
126}
127
42856c10 128bool fstype_is_network(const char *fstype) {
a05f97b3 129 static const char table[] =
ba89821c 130 "afs\0"
a05f97b3
LP
131 "cifs\0"
132 "smbfs\0"
da92ca5e 133 "sshfs\0"
a05f97b3 134 "ncpfs\0"
dac70dc7 135 "ncp\0"
a05f97b3
LP
136 "nfs\0"
137 "nfs4\0"
138 "gfs\0"
67608cad
LP
139 "gfs2\0"
140 "glusterfs\0";
141
142 const char *x;
143
144 x = startswith(fstype, "fuse.");
145 if (x)
146 fstype = x;
42856c10 147
a05f97b3 148 return nulstr_contains(table, fstype);
42856c10
LP
149}
150
5b6319dc
LP
151void rename_process(const char name[8]) {
152 assert(name);
153
5d6b1584
LP
154 /* This is a like a poor man's setproctitle(). It changes the
155 * comm field, argv[0], and also the glibc's internally used
156 * name of the process. For the first one a limit of 16 chars
157 * applies, to the second one usually one of 10 (i.e. length
158 * of "/sbin/init"), to the third one one of 7 (i.e. length of
159 * "systemd"). If you pass a longer string it will be
160 * truncated */
5b6319dc 161
5d6b1584 162 prctl(PR_SET_NAME, name);
5b6319dc
LP
163
164 if (program_invocation_name)
165 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
166
167 if (saved_argc > 0) {
168 int i;
169
170 if (saved_argv[0])
171 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
172
173 for (i = 1; i < saved_argc; i++) {
174 if (!saved_argv[i])
175 break;
176
29804cc1 177 memzero(saved_argv[i], strlen(saved_argv[i]));
9a0e6896
LP
178 }
179 }
5b6319dc
LP
180}
181
9d9951a4
HH
182int running_in_chroot(void) {
183 int ret;
184
185 ret = files_same("/proc/1/root", "/");
186 if (ret < 0)
187 return ret;
188
189 return ret == 0;
b4f10a5e
LP
190}
191
919ce0b7 192noreturn void freeze(void) {
720ce21d
LP
193
194 /* Make sure nobody waits for us on a socket anymore */
195 close_all_fds(NULL, 0);
196
c29597a1
LP
197 sync();
198
3c14d26c
LP
199 for (;;)
200 pause();
201}
202
e801700e 203static int do_execute(char **directories, usec_t timeout, char *argv[]) {
49681057 204 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
e801700e
ZJS
205 _cleanup_set_free_free_ Set *seen = NULL;
206 char **directory;
83cc030f 207
49681057
ZJS
208 /* We fork this all off from a child process so that we can
209 * somewhat cleanly make use of SIGALRM to set a time limit */
83cc030f 210
ce30c8dc
LP
211 (void) reset_all_signal_handlers();
212 (void) reset_signal_mask();
83cc030f 213
49681057 214 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 215
49681057
ZJS
216 pids = hashmap_new(NULL);
217 if (!pids)
218 return log_oom();
83cc030f 219
e801700e
ZJS
220 seen = set_new(&string_hash_ops);
221 if (!seen)
222 return log_oom();
83cc030f 223
e801700e
ZJS
224 STRV_FOREACH(directory, directories) {
225 _cleanup_closedir_ DIR *d;
226 struct dirent *de;
83cc030f 227
e801700e
ZJS
228 d = opendir(*directory);
229 if (!d) {
230 if (errno == ENOENT)
231 continue;
83cc030f 232
e801700e
ZJS
233 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
234 }
83cc030f 235
e801700e
ZJS
236 FOREACH_DIRENT(de, d, break) {
237 _cleanup_free_ char *path = NULL;
238 pid_t pid;
239 int r;
240
241 if (!dirent_is_file(de))
242 continue;
83cc030f 243
e801700e
ZJS
244 if (set_contains(seen, de->d_name)) {
245 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
246 continue;
247 }
248
249 r = set_put_strdup(seen, de->d_name);
250 if (r < 0)
251 return log_oom();
252
253 path = strjoin(*directory, "/", de->d_name, NULL);
254 if (!path)
255 return log_oom();
256
257 if (null_or_empty_path(path)) {
258 log_debug("%s is empty (a mask).", path);
259 continue;
7034e9db 260 }
83cc030f 261
e801700e
ZJS
262 pid = fork();
263 if (pid < 0) {
264 log_error_errno(errno, "Failed to fork: %m");
265 continue;
266 } else if (pid == 0) {
267 char *_argv[2];
83cc030f 268
e801700e 269 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 270
e801700e
ZJS
271 if (!argv) {
272 _argv[0] = path;
273 _argv[1] = NULL;
274 argv = _argv;
275 } else
276 argv[0] = path;
277
278 execv(path, argv);
279 return log_error_errno(errno, "Failed to execute %s: %m", path);
280 }
281
282 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 283
e801700e
ZJS
284 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
285 if (r < 0)
286 return log_oom();
287 path = NULL;
288 }
49681057 289 }
83cc030f 290
49681057
ZJS
291 /* Abort execution of this process after the timout. We simply
292 * rely on SIGALRM as default action terminating the process,
293 * and turn on alarm(). */
83cc030f 294
49681057
ZJS
295 if (timeout != USEC_INFINITY)
296 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
83cc030f 297
49681057
ZJS
298 while (!hashmap_isempty(pids)) {
299 _cleanup_free_ char *path = NULL;
300 pid_t pid;
aa62a893 301
49681057
ZJS
302 pid = PTR_TO_UINT(hashmap_first_key(pids));
303 assert(pid > 0);
83cc030f 304
49681057
ZJS
305 path = hashmap_remove(pids, UINT_TO_PTR(pid));
306 assert(path);
aa62a893 307
49681057
ZJS
308 wait_for_terminate_and_warn(path, pid, true);
309 }
aa62a893 310
49681057
ZJS
311 return 0;
312}
aa62a893 313
e801700e 314void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
49681057
ZJS
315 pid_t executor_pid;
316 int r;
e801700e
ZJS
317 char *name;
318 char **dirs = (char**) directories;
319
320 assert(!strv_isempty(dirs));
83cc030f 321
e801700e
ZJS
322 name = basename(dirs[0]);
323 assert(!isempty(name));
aa62a893 324
e801700e
ZJS
325 /* Executes all binaries in the directories in parallel and waits
326 * for them to finish. Optionally a timeout is applied. If a file
327 * with the same name exists in more than one directory, the
328 * earliest one wins. */
83cc030f 329
49681057
ZJS
330 executor_pid = fork();
331 if (executor_pid < 0) {
332 log_error_errno(errno, "Failed to fork: %m");
333 return;
334
335 } else if (executor_pid == 0) {
e801700e 336 r = do_execute(dirs, timeout, argv);
49681057 337 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
aa62a893 338 }
83cc030f 339
e801700e 340 wait_for_terminate_and_warn(name, executor_pid, true);
83cc030f
LP
341}
342
a88c8750
TG
343bool plymouth_running(void) {
344 return access("/run/plymouth/pid", F_OK) >= 0;
345}
346
4d6d6518
LP
347bool display_is_local(const char *display) {
348 assert(display);
349
350 return
351 display[0] == ':' &&
352 display[1] >= '0' &&
353 display[1] <= '9';
354}
355
356int socket_from_display(const char *display, char **path) {
357 size_t k;
358 char *f, *c;
359
360 assert(display);
361 assert(path);
362
363 if (!display_is_local(display))
364 return -EINVAL;
365
366 k = strspn(display+1, "0123456789");
367
f8294e41 368 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
369 if (!f)
370 return -ENOMEM;
371
372 c = stpcpy(f, "/tmp/.X11-unix/X");
373 memcpy(c, display+1, k);
374 c[k] = 0;
375
376 *path = f;
377
378 return 0;
379}
380
8092a428 381int glob_exists(const char *path) {
7fd1b19b 382 _cleanup_globfree_ glob_t g = {};
8d98da3f 383 int k;
8092a428
LP
384
385 assert(path);
386
8092a428
LP
387 errno = 0;
388 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
389
390 if (k == GLOB_NOMATCH)
8d98da3f 391 return 0;
8092a428 392 else if (k == GLOB_NOSPACE)
8d98da3f 393 return -ENOMEM;
8092a428 394 else if (k == 0)
8d98da3f 395 return !strv_isempty(g.gl_pathv);
8092a428 396 else
8d98da3f
ZJS
397 return errno ? -errno : -EIO;
398}
8092a428 399
8d98da3f
ZJS
400int glob_extend(char ***strv, const char *path) {
401 _cleanup_globfree_ glob_t g = {};
402 int k;
403 char **p;
404
405 errno = 0;
a8ccacf5 406 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
407
408 if (k == GLOB_NOMATCH)
409 return -ENOENT;
410 else if (k == GLOB_NOSPACE)
411 return -ENOMEM;
412 else if (k != 0 || strv_isempty(g.gl_pathv))
413 return errno ? -errno : -EIO;
414
415 STRV_FOREACH(p, g.gl_pathv) {
416 k = strv_extend(strv, *p);
417 if (k < 0)
418 break;
419 }
420
421 return k;
8092a428
LP
422}
423
94959f0f
LP
424int block_get_whole_disk(dev_t d, dev_t *ret) {
425 char *p, *s;
426 int r;
427 unsigned n, m;
428
429 assert(ret);
430
431 /* If it has a queue this is good enough for us */
432 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
433 return -ENOMEM;
434
435 r = access(p, F_OK);
436 free(p);
437
438 if (r >= 0) {
439 *ret = d;
440 return 0;
441 }
442
443 /* If it is a partition find the originating device */
444 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
445 return -ENOMEM;
446
447 r = access(p, F_OK);
448 free(p);
449
450 if (r < 0)
451 return -ENOENT;
452
453 /* Get parent dev_t */
454 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
455 return -ENOMEM;
456
457 r = read_one_line_file(p, &s);
458 free(p);
459
460 if (r < 0)
461 return r;
462
463 r = sscanf(s, "%u:%u", &m, &n);
464 free(s);
465
466 if (r != 2)
467 return -EINVAL;
468
469 /* Only return this if it is really good enough for us. */
470 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
471 return -ENOMEM;
472
473 r = access(p, F_OK);
474 free(p);
475
476 if (r >= 0) {
477 *ret = makedev(m, n);
478 return 0;
479 }
480
481 return -ENOENT;
482}
483
f41607a6
LP
484static const char *const ioprio_class_table[] = {
485 [IOPRIO_CLASS_NONE] = "none",
486 [IOPRIO_CLASS_RT] = "realtime",
487 [IOPRIO_CLASS_BE] = "best-effort",
488 [IOPRIO_CLASS_IDLE] = "idle"
489};
490
f8b69d1d 491DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
492
493static const char *const sigchld_code_table[] = {
494 [CLD_EXITED] = "exited",
495 [CLD_KILLED] = "killed",
496 [CLD_DUMPED] = "dumped",
497 [CLD_TRAPPED] = "trapped",
498 [CLD_STOPPED] = "stopped",
499 [CLD_CONTINUED] = "continued",
500};
501
502DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
503
504static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
505 [LOG_FAC(LOG_KERN)] = "kern",
506 [LOG_FAC(LOG_USER)] = "user",
507 [LOG_FAC(LOG_MAIL)] = "mail",
508 [LOG_FAC(LOG_DAEMON)] = "daemon",
509 [LOG_FAC(LOG_AUTH)] = "auth",
510 [LOG_FAC(LOG_SYSLOG)] = "syslog",
511 [LOG_FAC(LOG_LPR)] = "lpr",
512 [LOG_FAC(LOG_NEWS)] = "news",
513 [LOG_FAC(LOG_UUCP)] = "uucp",
514 [LOG_FAC(LOG_CRON)] = "cron",
515 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
516 [LOG_FAC(LOG_FTP)] = "ftp",
517 [LOG_FAC(LOG_LOCAL0)] = "local0",
518 [LOG_FAC(LOG_LOCAL1)] = "local1",
519 [LOG_FAC(LOG_LOCAL2)] = "local2",
520 [LOG_FAC(LOG_LOCAL3)] = "local3",
521 [LOG_FAC(LOG_LOCAL4)] = "local4",
522 [LOG_FAC(LOG_LOCAL5)] = "local5",
523 [LOG_FAC(LOG_LOCAL6)] = "local6",
524 [LOG_FAC(LOG_LOCAL7)] = "local7"
525};
526
f8b69d1d 527DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6 528
adb8ec96
EV
529bool log_facility_unshifted_is_valid(int facility) {
530 return facility >= 0 && facility <= LOG_FAC(~0);
531}
532
f41607a6
LP
533static const char *const log_level_table[] = {
534 [LOG_EMERG] = "emerg",
535 [LOG_ALERT] = "alert",
536 [LOG_CRIT] = "crit",
537 [LOG_ERR] = "err",
538 [LOG_WARNING] = "warning",
539 [LOG_NOTICE] = "notice",
540 [LOG_INFO] = "info",
541 [LOG_DEBUG] = "debug"
542};
543
f8b69d1d 544DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6 545
adb8ec96
EV
546bool log_level_is_valid(int level) {
547 return level >= 0 && level <= LOG_DEBUG;
548}
549
f41607a6
LP
550static const char* const sched_policy_table[] = {
551 [SCHED_OTHER] = "other",
552 [SCHED_BATCH] = "batch",
553 [SCHED_IDLE] = "idle",
554 [SCHED_FIFO] = "fifo",
555 [SCHED_RR] = "rr"
556};
557
f8b69d1d 558DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 559
65457142
FC
560bool kexec_loaded(void) {
561 bool loaded = false;
562 char *s;
563
564 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
565 if (s[0] == '1')
566 loaded = true;
567 free(s);
568 }
569 return loaded;
570}
fb9de93d 571
87d2c1ff
LP
572int prot_from_flags(int flags) {
573
574 switch (flags & O_ACCMODE) {
575
576 case O_RDONLY:
577 return PROT_READ;
578
579 case O_WRONLY:
580 return PROT_WRITE;
581
582 case O_RDWR:
583 return PROT_READ|PROT_WRITE;
584
585 default:
586 return -EINVAL;
587 }
7c99e0c1 588}
689b9a22 589
55d7bfc1
LP
590void* memdup(const void *p, size_t l) {
591 void *r;
592
593 assert(p);
594
595 r = malloc(l);
596 if (!r)
597 return NULL;
598
599 memcpy(r, p, l);
600 return r;
601}
bb99a35a 602
9bdc770c 603int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16 604 bool stdout_is_tty, stderr_is_tty;
8a7c93d8
LP
605 pid_t parent_pid, agent_pid;
606 sigset_t ss, saved_ss;
6bb92a16
LP
607 unsigned n, i;
608 va_list ap;
609 char **l;
610
611 assert(pid);
612 assert(path);
613
6bb92a16
LP
614 /* Spawns a temporary TTY agent, making sure it goes away when
615 * we go away */
616
8a7c93d8
LP
617 parent_pid = getpid();
618
619 /* First we temporarily block all signals, so that the new
620 * child has them blocked initially. This way, we can be sure
621 * that SIGTERMs are not lost we might send to the agent. */
622 assert_se(sigfillset(&ss) >= 0);
623 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
624
6bb92a16 625 agent_pid = fork();
8a7c93d8
LP
626 if (agent_pid < 0) {
627 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16 628 return -errno;
8a7c93d8 629 }
6bb92a16
LP
630
631 if (agent_pid != 0) {
8a7c93d8 632 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16
LP
633 *pid = agent_pid;
634 return 0;
635 }
636
637 /* In the child:
638 *
639 * Make sure the agent goes away when the parent dies */
640 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
641 _exit(EXIT_FAILURE);
642
8a7c93d8
LP
643 /* Make sure we actually can kill the agent, if we need to, in
644 * case somebody invoked us from a shell script that trapped
645 * SIGTERM or so... */
ce30c8dc
LP
646 (void) reset_all_signal_handlers();
647 (void) reset_signal_mask();
8a7c93d8 648
6bb92a16 649 /* Check whether our parent died before we were able
8a7c93d8 650 * to set the death signal and unblock the signals */
6bb92a16
LP
651 if (getppid() != parent_pid)
652 _exit(EXIT_SUCCESS);
653
654 /* Don't leak fds to the agent */
9bdc770c 655 close_all_fds(except, n_except);
6bb92a16
LP
656
657 stdout_is_tty = isatty(STDOUT_FILENO);
658 stderr_is_tty = isatty(STDERR_FILENO);
659
660 if (!stdout_is_tty || !stderr_is_tty) {
8a7c93d8
LP
661 int fd;
662
6bb92a16
LP
663 /* Detach from stdout/stderr. and reopen
664 * /dev/tty for them. This is important to
665 * ensure that when systemctl is started via
666 * popen() or a similar call that expects to
667 * read EOF we actually do generate EOF and
668 * not delay this indefinitely by because we
669 * keep an unused copy of stdin around. */
670 fd = open("/dev/tty", O_WRONLY);
671 if (fd < 0) {
56f64d95 672 log_error_errno(errno, "Failed to open /dev/tty: %m");
6bb92a16
LP
673 _exit(EXIT_FAILURE);
674 }
675
676 if (!stdout_is_tty)
677 dup2(fd, STDOUT_FILENO);
678
679 if (!stderr_is_tty)
680 dup2(fd, STDERR_FILENO);
681
682 if (fd > 2)
683 close(fd);
684 }
685
686 /* Count arguments */
687 va_start(ap, path);
688 for (n = 0; va_arg(ap, char*); n++)
689 ;
690 va_end(ap);
691
692 /* Allocate strv */
693 l = alloca(sizeof(char *) * (n + 1));
694
695 /* Fill in arguments */
696 va_start(ap, path);
697 for (i = 0; i <= n; i++)
698 l[i] = va_arg(ap, char*);
699 va_end(ap);
700
701 execv(path, l);
702 _exit(EXIT_FAILURE);
703}
68faf98c 704
3d7415f4
LP
705bool http_etag_is_valid(const char *etag) {
706 if (isempty(etag))
707 return false;
708
709 if (!endswith(etag, "\""))
710 return false;
711
712 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
713 return false;
714
715 return true;
716}
717
a2e03378
LP
718bool http_url_is_valid(const char *url) {
719 const char *p;
49dbfa7b 720
a2e03378
LP
721 if (isempty(url))
722 return false;
49dbfa7b 723
a2e03378
LP
724 p = startswith(url, "http://");
725 if (!p)
726 p = startswith(url, "https://");
727 if (!p)
728 return false;
49dbfa7b 729
a2e03378
LP
730 if (isempty(p))
731 return false;
49dbfa7b 732
a2e03378
LP
733 return ascii_is_valid(p);
734}
49dbfa7b 735
a2e03378
LP
736bool documentation_url_is_valid(const char *url) {
737 const char *p;
738
739 if (isempty(url))
740 return false;
741
742 if (http_url_is_valid(url))
49dbfa7b
LP
743 return true;
744
a2e03378
LP
745 p = startswith(url, "file:/");
746 if (!p)
747 p = startswith(url, "info:");
748 if (!p)
749 p = startswith(url, "man:");
750
751 if (isempty(p))
752 return false;
753
754 return ascii_is_valid(p);
49dbfa7b 755}
9be346c9
HH
756
757bool in_initrd(void) {
73020ab2 758 static int saved = -1;
825c6fe5 759 struct statfs s;
8f33b5b8 760
825c6fe5
LP
761 if (saved >= 0)
762 return saved;
763
764 /* We make two checks here:
765 *
766 * 1. the flag file /etc/initrd-release must exist
767 * 2. the root file system must be a memory file system
768 *
769 * The second check is extra paranoia, since misdetecting an
770 * initrd can have bad bad consequences due the initrd
771 * emptying when transititioning to the main systemd.
772 */
773
774 saved = access("/etc/initrd-release", F_OK) >= 0 &&
775 statfs("/", &s) >= 0 &&
943aad8c 776 is_temporary_fs(&s);
9be346c9 777
8f33b5b8 778 return saved;
9be346c9 779}
069cfc85 780
a9e12476
KS
781/* hey glibc, APIs with callbacks without a user pointer are so useless */
782void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 783 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
784 size_t l, u, idx;
785 const void *p;
786 int comparison;
787
788 l = 0;
789 u = nmemb;
790 while (l < u) {
791 idx = (l + u) / 2;
792 p = (void *)(((const char *) base) + (idx * size));
793 comparison = compar(key, p, arg);
794 if (comparison < 0)
795 u = idx;
796 else if (comparison > 0)
797 l = idx + 1;
798 else
799 return (void *)p;
800 }
801 return NULL;
802}
09017585 803
240dbaa4
LP
804int on_ac_power(void) {
805 bool found_offline = false, found_online = false;
806 _cleanup_closedir_ DIR *d = NULL;
807
808 d = opendir("/sys/class/power_supply");
809 if (!d)
6d890034 810 return errno == ENOENT ? true : -errno;
240dbaa4
LP
811
812 for (;;) {
813 struct dirent *de;
240dbaa4
LP
814 _cleanup_close_ int fd = -1, device = -1;
815 char contents[6];
816 ssize_t n;
240dbaa4 817
3fd11280
FW
818 errno = 0;
819 de = readdir(d);
820 if (!de && errno != 0)
821 return -errno;
240dbaa4
LP
822
823 if (!de)
824 break;
825
a34bf9db 826 if (hidden_file(de->d_name))
240dbaa4
LP
827 continue;
828
829 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
830 if (device < 0) {
831 if (errno == ENOENT || errno == ENOTDIR)
832 continue;
833
834 return -errno;
835 }
836
837 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
838 if (fd < 0) {
839 if (errno == ENOENT)
840 continue;
841
842 return -errno;
843 }
844
845 n = read(fd, contents, sizeof(contents));
846 if (n < 0)
847 return -errno;
848
849 if (n != 6 || memcmp(contents, "Mains\n", 6))
850 continue;
851
03e334a1 852 safe_close(fd);
240dbaa4
LP
853 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
854 if (fd < 0) {
855 if (errno == ENOENT)
856 continue;
857
858 return -errno;
859 }
860
861 n = read(fd, contents, sizeof(contents));
862 if (n < 0)
863 return -errno;
864
865 if (n != 2 || contents[1] != '\n')
866 return -EIO;
867
868 if (contents[0] == '1') {
869 found_online = true;
870 break;
871 } else if (contents[0] == '0')
872 found_offline = true;
873 else
874 return -EIO;
875 }
876
877 return found_online || !found_offline;
878}
fabe5c0e 879
ca2d3784
ZJS
880void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
881 size_t a, newalloc;
392d5b37
LP
882 void *q;
883
98088803 884 assert(p);
e93c33d4
SL
885 assert(allocated);
886
392d5b37
LP
887 if (*allocated >= need)
888 return *p;
889
ca2d3784
ZJS
890 newalloc = MAX(need * 2, 64u / size);
891 a = newalloc * size;
98088803
LP
892
893 /* check for overflows */
ca2d3784 894 if (a < size * need)
98088803
LP
895 return NULL;
896
392d5b37
LP
897 q = realloc(*p, a);
898 if (!q)
899 return NULL;
900
901 *p = q;
ca2d3784 902 *allocated = newalloc;
392d5b37
LP
903 return q;
904}
aa96c6cb 905
ca2d3784 906void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 907 size_t prev;
4545a231
DH
908 uint8_t *q;
909
98088803
LP
910 assert(p);
911 assert(allocated);
912
913 prev = *allocated;
914
ca2d3784 915 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
916 if (!q)
917 return NULL;
918
919 if (*allocated > prev)
ca2d3784 920 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
921
922 return q;
923}
924
aa96c6cb
LP
925bool id128_is_valid(const char *s) {
926 size_t i, l;
927
928 l = strlen(s);
929 if (l == 32) {
930
931 /* Simple formatted 128bit hex string */
932
933 for (i = 0; i < l; i++) {
934 char c = s[i];
935
936 if (!(c >= '0' && c <= '9') &&
937 !(c >= 'a' && c <= 'z') &&
938 !(c >= 'A' && c <= 'Z'))
939 return false;
940 }
941
942 } else if (l == 36) {
943
944 /* Formatted UUID */
945
946 for (i = 0; i < l; i++) {
947 char c = s[i];
948
949 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
950 if (c != '-')
951 return false;
952 } else {
953 if (!(c >= '0' && c <= '9') &&
954 !(c >= 'a' && c <= 'z') &&
955 !(c >= 'A' && c <= 'Z'))
956 return false;
957 }
958 }
959
960 } else
961 return false;
962
963 return true;
964}
7085053a 965
74df0fca 966int shall_restore_state(void) {
1a299299 967 _cleanup_free_ char *value = NULL;
74df0fca 968 int r;
295edddf 969
1a299299 970 r = get_proc_cmdline_key("systemd.restore_state=", &value);
74df0fca
LP
971 if (r < 0)
972 return r;
1a299299
LP
973 if (r == 0)
974 return true;
295edddf 975
1a299299 976 return parse_boolean(value) != 0;
74df0fca
LP
977}
978
979int proc_cmdline(char **ret) {
b5884878 980 assert(ret);
295edddf 981
75f86906 982 if (detect_container() > 0)
b5884878
LP
983 return get_process_cmdline(1, 0, false, ret);
984 else
985 return read_one_line_file("/proc/cmdline", ret);
295edddf 986}
bc9fd78c 987
059cb385 988int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4 989 _cleanup_free_ char *line = NULL;
f32d2db1 990 const char *p;
141a79f4
ZJS
991 int r;
992
059cb385
LP
993 assert(parse_item);
994
141a79f4
ZJS
995 r = proc_cmdline(&line);
996 if (r < 0)
b5884878 997 return r;
141a79f4 998
f32d2db1
LP
999 p = line;
1000 for (;;) {
1001 _cleanup_free_ char *word = NULL;
1002 char *value = NULL;
141a79f4 1003
12ba2c44 1004 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
f32d2db1
LP
1005 if (r < 0)
1006 return r;
1007 if (r == 0)
1008 break;
141a79f4 1009
059cb385
LP
1010 /* Filter out arguments that are intended only for the
1011 * initrd */
1012 if (!in_initrd() && startswith(word, "rd."))
1013 continue;
1014
1015 value = strchr(word, '=');
1016 if (value)
1017 *(value++) = 0;
1018
1019 r = parse_item(word, value);
1020 if (r < 0)
141a79f4 1021 return r;
141a79f4
ZJS
1022 }
1023
1024 return 0;
1025}
1026
1a299299
LP
1027int get_proc_cmdline_key(const char *key, char **value) {
1028 _cleanup_free_ char *line = NULL, *ret = NULL;
1029 bool found = false;
1030 const char *p;
1031 int r;
1032
1033 assert(key);
1034
1035 r = proc_cmdline(&line);
1036 if (r < 0)
1037 return r;
1038
1039 p = line;
1040 for (;;) {
1041 _cleanup_free_ char *word = NULL;
1042 const char *e;
1043
12ba2c44 1044 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
1a299299
LP
1045 if (r < 0)
1046 return r;
1047 if (r == 0)
1048 break;
1049
1050 /* Filter out arguments that are intended only for the
1051 * initrd */
1052 if (!in_initrd() && startswith(word, "rd."))
1053 continue;
1054
1055 if (value) {
1056 e = startswith(word, key);
1057 if (!e)
1058 continue;
1059
1060 r = free_and_strdup(&ret, e);
1061 if (r < 0)
1062 return r;
1063
1064 found = true;
1065 } else {
1066 if (streq(word, key))
1067 found = true;
1068 }
1069 }
1070
1071 if (value) {
1072 *value = ret;
1073 ret = NULL;
1074 }
1075
1076 return found;
1077
1078}
1079
bc9fd78c
LP
1080int container_get_leader(const char *machine, pid_t *pid) {
1081 _cleanup_free_ char *s = NULL, *class = NULL;
1082 const char *p;
1083 pid_t leader;
1084 int r;
1085
1086 assert(machine);
1087 assert(pid);
1088
b9a8d250
LP
1089 if (!machine_name_is_valid(machine))
1090 return -EINVAL;
1091
63c372cb 1092 p = strjoina("/run/systemd/machines/", machine);
bc9fd78c
LP
1093 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
1094 if (r == -ENOENT)
1095 return -EHOSTDOWN;
1096 if (r < 0)
1097 return r;
1098 if (!s)
1099 return -EIO;
1100
1101 if (!streq_ptr(class, "container"))
1102 return -EIO;
1103
1104 r = parse_pid(s, &leader);
1105 if (r < 0)
1106 return r;
1107 if (leader <= 1)
1108 return -EIO;
1109
1110 *pid = leader;
1111 return 0;
1112}
1113
671c3419
RM
1114int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
1115 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
359a06aa 1116 int rfd = -1;
bc9fd78c
LP
1117
1118 assert(pid >= 0);
bc9fd78c 1119
878cd7e9
LP
1120 if (mntns_fd) {
1121 const char *mntns;
a4475f57 1122
878cd7e9
LP
1123 mntns = procfs_file_alloca(pid, "ns/mnt");
1124 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1125 if (mntnsfd < 0)
1126 return -errno;
1127 }
bc9fd78c 1128
878cd7e9
LP
1129 if (pidns_fd) {
1130 const char *pidns;
1131
1132 pidns = procfs_file_alloca(pid, "ns/pid");
1133 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1134 if (pidnsfd < 0)
1135 return -errno;
1136 }
1137
1138 if (netns_fd) {
1139 const char *netns;
1140
1141 netns = procfs_file_alloca(pid, "ns/net");
1142 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1143 if (netnsfd < 0)
1144 return -errno;
1145 }
1146
671c3419
RM
1147 if (userns_fd) {
1148 const char *userns;
1149
1150 userns = procfs_file_alloca(pid, "ns/user");
1151 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1152 if (usernsfd < 0 && errno != ENOENT)
1153 return -errno;
1154 }
1155
878cd7e9
LP
1156 if (root_fd) {
1157 const char *root;
1158
1159 root = procfs_file_alloca(pid, "root");
1160 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
1161 if (rfd < 0)
1162 return -errno;
1163 }
1164
1165 if (pidns_fd)
1166 *pidns_fd = pidnsfd;
bc9fd78c 1167
878cd7e9
LP
1168 if (mntns_fd)
1169 *mntns_fd = mntnsfd;
1170
1171 if (netns_fd)
1172 *netns_fd = netnsfd;
1173
671c3419
RM
1174 if (userns_fd)
1175 *userns_fd = usernsfd;
1176
878cd7e9
LP
1177 if (root_fd)
1178 *root_fd = rfd;
1179
671c3419 1180 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
bc9fd78c
LP
1181
1182 return 0;
1183}
1184
671c3419
RM
1185int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
1186 if (userns_fd >= 0) {
1187 /* Can't setns to your own userns, since then you could
1188 * escalate from non-root to root in your own namespace, so
1189 * check if namespaces equal before attempting to enter. */
1190 _cleanup_free_ char *userns_fd_path = NULL;
1191 int r;
1192 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
1193 return -ENOMEM;
1194
1195 r = files_same(userns_fd_path, "/proc/self/ns/user");
1196 if (r < 0)
1197 return r;
1198 if (r)
1199 userns_fd = -1;
1200 }
bc9fd78c 1201
878cd7e9
LP
1202 if (pidns_fd >= 0)
1203 if (setns(pidns_fd, CLONE_NEWPID) < 0)
1204 return -errno;
a4475f57 1205
878cd7e9
LP
1206 if (mntns_fd >= 0)
1207 if (setns(mntns_fd, CLONE_NEWNS) < 0)
1208 return -errno;
bc9fd78c 1209
878cd7e9
LP
1210 if (netns_fd >= 0)
1211 if (setns(netns_fd, CLONE_NEWNET) < 0)
1212 return -errno;
bc9fd78c 1213
671c3419
RM
1214 if (userns_fd >= 0)
1215 if (setns(userns_fd, CLONE_NEWUSER) < 0)
1216 return -errno;
1217
878cd7e9
LP
1218 if (root_fd >= 0) {
1219 if (fchdir(root_fd) < 0)
1220 return -errno;
1221
1222 if (chroot(".") < 0)
1223 return -errno;
1224 }
bc9fd78c 1225
b4da6d6b 1226 return reset_uid_gid();
bc9fd78c 1227}
bf108e55 1228
ac45f971 1229unsigned long personality_from_string(const char *p) {
6afc95b7
LP
1230
1231 /* Parse a personality specifier. We introduce our own
1232 * identifiers that indicate specific ABIs, rather than just
1233 * hints regarding the register size, since we want to keep
1234 * things open for multiple locally supported ABIs for the
1235 * same register size. We try to reuse the ABI identifiers
1236 * used by libseccomp. */
1237
1238#if defined(__x86_64__)
1239
1240 if (streq(p, "x86"))
1241 return PER_LINUX32;
1242
1243 if (streq(p, "x86-64"))
1244 return PER_LINUX;
1245
1246#elif defined(__i386__)
1247
1248 if (streq(p, "x86"))
1249 return PER_LINUX;
7517f51e
HB
1250
1251#elif defined(__s390x__)
1252
1253 if (streq(p, "s390"))
1254 return PER_LINUX32;
1255
1256 if (streq(p, "s390x"))
1257 return PER_LINUX;
1258
1259#elif defined(__s390__)
1260
1261 if (streq(p, "s390"))
1262 return PER_LINUX;
6afc95b7
LP
1263#endif
1264
050f7277 1265 return PERSONALITY_INVALID;
6afc95b7 1266}
ac45f971
LP
1267
1268const char* personality_to_string(unsigned long p) {
1269
1270#if defined(__x86_64__)
1271
1272 if (p == PER_LINUX32)
1273 return "x86";
1274
1275 if (p == PER_LINUX)
1276 return "x86-64";
1277
1278#elif defined(__i386__)
1279
1280 if (p == PER_LINUX)
1281 return "x86";
7517f51e
HB
1282
1283#elif defined(__s390x__)
1284
1285 if (p == PER_LINUX)
1286 return "s390x";
1287
1288 if (p == PER_LINUX32)
1289 return "s390";
1290
1291#elif defined(__s390__)
1292
1293 if (p == PER_LINUX)
1294 return "s390";
1295
ac45f971
LP
1296#endif
1297
1298 return NULL;
1299}
1c231f56
LP
1300
1301uint64_t physical_memory(void) {
1302 long mem;
1303
1304 /* We return this as uint64_t in case we are running as 32bit
1305 * process on a 64bit kernel with huge amounts of memory */
1306
1307 mem = sysconf(_SC_PHYS_PAGES);
1308 assert(mem > 0);
1309
1310 return (uint64_t) mem * (uint64_t) page_size();
1311}
6db615c1 1312
966bff26 1313int update_reboot_param_file(const char *param) {
c5220a94
MO
1314 int r = 0;
1315
1316 if (param) {
4c1fc3e4 1317 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
c5220a94 1318 if (r < 0)
e53fc357 1319 return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
c5220a94 1320 } else
e53fc357 1321 (void) unlink(REBOOT_PARAM_FILE);
c5220a94 1322
e53fc357 1323 return 0;
c5220a94 1324}
6d313367 1325
3d7415f4
LP
1326int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
1327 int a = 0, b = 0, c = 0;
1328 int k;
1329
1330 assert(p);
1331 assert(*p);
1332 assert(priority);
1333
1334 if ((*p)[0] != '<')
1335 return 0;
1336
1337 if (!strchr(*p, '>'))
1338 return 0;
1339
1340 if ((*p)[2] == '>') {
1341 c = undecchar((*p)[1]);
1342 k = 3;
1343 } else if ((*p)[3] == '>') {
1344 b = undecchar((*p)[1]);
1345 c = undecchar((*p)[2]);
1346 k = 4;
1347 } else if ((*p)[4] == '>') {
1348 a = undecchar((*p)[1]);
1349 b = undecchar((*p)[2]);
1350 c = undecchar((*p)[3]);
1351 k = 5;
1352 } else
1353 return 0;
1354
1355 if (a < 0 || b < 0 || c < 0 ||
1356 (!with_facility && (a || b || c > 7)))
1357 return 0;
1358
1359 if (with_facility)
1360 *priority = a*100 + b*10 + c;
1361 else
1362 *priority = (*priority & LOG_FACMASK) | c;
1363
1364 *p += k;
1365 return 1;
1366}
9cad100e 1367
3f6fd1ba
LP
1368int version(void) {
1369 puts(PACKAGE_STRING "\n"
1370 SYSTEMD_FEATURES);
1371 return 0;
1372}
8dd4c05b
LP
1373
1374bool fdname_is_valid(const char *s) {
1375 const char *p;
1376
0a3bb96e 1377 /* Validates a name for $LISTEN_FDNAMES. We basically allow
8dd4c05b
LP
1378 * everything ASCII that's not a control character. Also, as
1379 * special exception the ":" character is not allowed, as we
0a3bb96e 1380 * use that as field separator in $LISTEN_FDNAMES.
8dd4c05b 1381 *
0a3bb96e
LP
1382 * Note that the empty string is explicitly allowed
1383 * here. However, we limit the length of the names to 255
1384 * characters. */
8dd4c05b
LP
1385
1386 if (!s)
1387 return false;
1388
1389 for (p = s; *p; p++) {
1390 if (*p < ' ')
1391 return false;
1392 if (*p >= 127)
1393 return false;
1394 if (*p == ':')
1395 return false;
1396 }
1397
1398 return p - s < 256;
1399}
257b0719
EV
1400
1401bool oom_score_adjust_is_valid(int oa) {
1402 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
1403}