]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
logind: allow users to override their own suspend/sleep inhibitors
[thirdparty/systemd.git] / src / shared / 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
60918275
LP
22#include <assert.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
85261803 26#include <stdlib.h>
034c6ed7
LP
27#include <signal.h>
28#include <stdio.h>
1dccbe19
LP
29#include <syslog.h>
30#include <sched.h>
31#include <sys/resource.h>
ef886c6a 32#include <linux/sched.h>
a9f5d454
LP
33#include <sys/types.h>
34#include <sys/stat.h>
3a0ecb08 35#include <fcntl.h>
a0d40ac5 36#include <dirent.h>
601f6a1e
LP
37#include <sys/ioctl.h>
38#include <linux/vt.h>
39#include <linux/tiocl.h>
80876c20
LP
40#include <termios.h>
41#include <stdarg.h>
42#include <sys/inotify.h>
43#include <sys/poll.h>
8d567588 44#include <libgen.h>
3177a7fa 45#include <ctype.h>
5b6319dc 46#include <sys/prctl.h>
ef2f1067
LP
47#include <sys/utsname.h>
48#include <pwd.h>
4fd5948e 49#include <netinet/ip.h>
3fe5e5d4 50#include <linux/kd.h>
afea26ad 51#include <dlfcn.h>
2e78aa99 52#include <sys/wait.h>
7948c4df 53#include <sys/time.h>
8092a428 54#include <glob.h>
4b67834e 55#include <grp.h>
87d2c1ff 56#include <sys/mman.h>
825c6fe5
LP
57#include <sys/vfs.h>
58#include <linux/magic.h>
60918275
LP
59
60#include "macro.h"
61#include "util.h"
1dccbe19
LP
62#include "ioprio.h"
63#include "missing.h"
a9f5d454 64#include "log.h"
65d2ebdc 65#include "strv.h"
e51bc1a2 66#include "label.h"
9eb977db 67#include "path-util.h"
d06dacd0 68#include "exit-status.h"
83cc030f 69#include "hashmap.h"
56cf987f 70
9a0e6896
LP
71int saved_argc = 0;
72char **saved_argv = NULL;
73
37f85e66 74size_t page_size(void) {
75 static __thread size_t pgsz = 0;
76 long r;
77
87d2c1ff 78 if (_likely_(pgsz > 0))
37f85e66 79 return pgsz;
80
e67f47e5
LP
81 r = sysconf(_SC_PAGESIZE);
82 assert(r > 0);
37f85e66 83
84 pgsz = (size_t) r;
37f85e66 85 return pgsz;
86}
87
e05797fb
LP
88bool streq_ptr(const char *a, const char *b) {
89
90 /* Like streq(), but tries to make sense of NULL pointers */
91
92 if (a && b)
93 return streq(a, b);
94
95 if (!a && !b)
96 return true;
97
98 return false;
99}
100
47be870b 101usec_t now(clockid_t clock_id) {
60918275
LP
102 struct timespec ts;
103
47be870b 104 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
105
106 return timespec_load(&ts);
107}
108
63983207 109dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
871d7de4
LP
110 assert(ts);
111
112 ts->realtime = now(CLOCK_REALTIME);
113 ts->monotonic = now(CLOCK_MONOTONIC);
114
115 return ts;
116}
117
a185c5aa
LP
118dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
119 int64_t delta;
120 assert(ts);
121
122 ts->realtime = u;
123
124 if (u == 0)
125 ts->monotonic = 0;
126 else {
127 delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
128
129 ts->monotonic = now(CLOCK_MONOTONIC);
130
131 if ((int64_t) ts->monotonic > delta)
132 ts->monotonic -= delta;
133 else
134 ts->monotonic = 0;
135 }
136
137 return ts;
138}
139
60918275
LP
140usec_t timespec_load(const struct timespec *ts) {
141 assert(ts);
142
143 return
144 (usec_t) ts->tv_sec * USEC_PER_SEC +
145 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
146}
147
148struct timespec *timespec_store(struct timespec *ts, usec_t u) {
149 assert(ts);
150
151 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
152 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
153
154 return ts;
155}
156
157usec_t timeval_load(const struct timeval *tv) {
158 assert(tv);
159
160 return
161 (usec_t) tv->tv_sec * USEC_PER_SEC +
162 (usec_t) tv->tv_usec;
163}
164
165struct timeval *timeval_store(struct timeval *tv, usec_t u) {
166 assert(tv);
167
168 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
169 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
170
171 return tv;
172}
173
174bool endswith(const char *s, const char *postfix) {
175 size_t sl, pl;
176
177 assert(s);
178 assert(postfix);
179
180 sl = strlen(s);
181 pl = strlen(postfix);
182
d4d0d4db
LP
183 if (pl == 0)
184 return true;
185
60918275
LP
186 if (sl < pl)
187 return false;
188
189 return memcmp(s + sl - pl, postfix, pl) == 0;
190}
191
192bool startswith(const char *s, const char *prefix) {
193 size_t sl, pl;
194
195 assert(s);
196 assert(prefix);
197
198 sl = strlen(s);
199 pl = strlen(prefix);
200
d4d0d4db
LP
201 if (pl == 0)
202 return true;
203
60918275
LP
204 if (sl < pl)
205 return false;
206
207 return memcmp(s, prefix, pl) == 0;
208}
209
3177a7fa
MAP
210bool startswith_no_case(const char *s, const char *prefix) {
211 size_t sl, pl;
212 unsigned i;
213
214 assert(s);
215 assert(prefix);
216
217 sl = strlen(s);
218 pl = strlen(prefix);
219
220 if (pl == 0)
221 return true;
222
223 if (sl < pl)
224 return false;
225
e67f47e5 226 for(i = 0; i < pl; ++i)
3177a7fa
MAP
227 if (tolower(s[i]) != tolower(prefix[i]))
228 return false;
3177a7fa
MAP
229
230 return true;
231}
232
79d6d816
LP
233bool first_word(const char *s, const char *word) {
234 size_t sl, wl;
235
236 assert(s);
237 assert(word);
238
239 sl = strlen(s);
240 wl = strlen(word);
241
242 if (sl < wl)
243 return false;
244
d4d0d4db
LP
245 if (wl == 0)
246 return true;
247
79d6d816
LP
248 if (memcmp(s, word, wl) != 0)
249 return false;
250
d4d0d4db
LP
251 return s[wl] == 0 ||
252 strchr(WHITESPACE, s[wl]);
79d6d816
LP
253}
254
42f4e3c4 255int close_nointr(int fd) {
60918275
LP
256 assert(fd >= 0);
257
258 for (;;) {
259 int r;
260
48f82119
LP
261 r = close(fd);
262 if (r >= 0)
60918275
LP
263 return r;
264
265 if (errno != EINTR)
48f82119 266 return -errno;
60918275
LP
267 }
268}
85261803 269
85f136b5 270void close_nointr_nofail(int fd) {
80876c20 271 int saved_errno = errno;
85f136b5
LP
272
273 /* like close_nointr() but cannot fail, and guarantees errno
274 * is unchanged */
275
276 assert_se(close_nointr(fd) == 0);
80876c20
LP
277
278 errno = saved_errno;
85f136b5
LP
279}
280
5b6319dc
LP
281void close_many(const int fds[], unsigned n_fd) {
282 unsigned i;
283
284 for (i = 0; i < n_fd; i++)
285 close_nointr_nofail(fds[i]);
286}
287
85261803
LP
288int parse_boolean(const char *v) {
289 assert(v);
290
44d8db9e 291 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 292 return 1;
44d8db9e 293 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
294 return 0;
295
296 return -EINVAL;
297}
298
3ba686c1 299int parse_pid(const char *s, pid_t* ret_pid) {
0b172489 300 unsigned long ul = 0;
3ba686c1
LP
301 pid_t pid;
302 int r;
303
304 assert(s);
305 assert(ret_pid);
306
e67f47e5
LP
307 r = safe_atolu(s, &ul);
308 if (r < 0)
3ba686c1
LP
309 return r;
310
311 pid = (pid_t) ul;
312
313 if ((unsigned long) pid != ul)
314 return -ERANGE;
315
316 if (pid <= 0)
317 return -ERANGE;
318
319 *ret_pid = pid;
320 return 0;
321}
322
034a2a52
LP
323int parse_uid(const char *s, uid_t* ret_uid) {
324 unsigned long ul = 0;
325 uid_t uid;
326 int r;
327
328 assert(s);
329 assert(ret_uid);
330
e67f47e5
LP
331 r = safe_atolu(s, &ul);
332 if (r < 0)
034a2a52
LP
333 return r;
334
335 uid = (uid_t) ul;
336
337 if ((unsigned long) uid != ul)
338 return -ERANGE;
339
340 *ret_uid = uid;
341 return 0;
342}
343
85261803
LP
344int safe_atou(const char *s, unsigned *ret_u) {
345 char *x = NULL;
034c6ed7 346 unsigned long l;
85261803
LP
347
348 assert(s);
349 assert(ret_u);
350
351 errno = 0;
352 l = strtoul(s, &x, 0);
353
354 if (!x || *x || errno)
355 return errno ? -errno : -EINVAL;
356
034c6ed7 357 if ((unsigned long) (unsigned) l != l)
85261803
LP
358 return -ERANGE;
359
360 *ret_u = (unsigned) l;
361 return 0;
362}
363
364int safe_atoi(const char *s, int *ret_i) {
365 char *x = NULL;
034c6ed7 366 long l;
85261803
LP
367
368 assert(s);
369 assert(ret_i);
370
371 errno = 0;
372 l = strtol(s, &x, 0);
373
374 if (!x || *x || errno)
375 return errno ? -errno : -EINVAL;
376
034c6ed7 377 if ((long) (int) l != l)
85261803
LP
378 return -ERANGE;
379
034c6ed7
LP
380 *ret_i = (int) l;
381 return 0;
382}
383
034c6ed7
LP
384int safe_atollu(const char *s, long long unsigned *ret_llu) {
385 char *x = NULL;
386 unsigned long long l;
387
388 assert(s);
389 assert(ret_llu);
390
391 errno = 0;
392 l = strtoull(s, &x, 0);
393
394 if (!x || *x || errno)
395 return errno ? -errno : -EINVAL;
396
397 *ret_llu = l;
398 return 0;
399}
400
401int safe_atolli(const char *s, long long int *ret_lli) {
402 char *x = NULL;
403 long long l;
404
405 assert(s);
406 assert(ret_lli);
407
408 errno = 0;
409 l = strtoll(s, &x, 0);
410
411 if (!x || *x || errno)
412 return errno ? -errno : -EINVAL;
413
414 *ret_lli = l;
85261803
LP
415 return 0;
416}
a41e8209 417
a41e8209 418/* Split a string into words. */
65d2ebdc 419char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
420 char *current;
421
422 current = *state ? *state : (char*) c;
423
424 if (!*current || *c == 0)
425 return NULL;
426
65d2ebdc
LP
427 current += strspn(current, separator);
428 *l = strcspn(current, separator);
82919e3d
LP
429 *state = current+*l;
430
431 return (char*) current;
432}
433
034c6ed7
LP
434/* Split a string into words, but consider strings enclosed in '' and
435 * "" as words even if they include spaces. */
436char *split_quoted(const char *c, size_t *l, char **state) {
0bab36f2
LP
437 char *current, *e;
438 bool escaped = false;
034c6ed7
LP
439
440 current = *state ? *state : (char*) c;
441
442 if (!*current || *c == 0)
443 return NULL;
444
445 current += strspn(current, WHITESPACE);
446
447 if (*current == '\'') {
448 current ++;
034c6ed7 449
0bab36f2
LP
450 for (e = current; *e; e++) {
451 if (escaped)
452 escaped = false;
453 else if (*e == '\\')
454 escaped = true;
455 else if (*e == '\'')
456 break;
457 }
458
459 *l = e-current;
460 *state = *e == 0 ? e : e+1;
034c6ed7
LP
461 } else if (*current == '\"') {
462 current ++;
034c6ed7 463
0bab36f2
LP
464 for (e = current; *e; e++) {
465 if (escaped)
466 escaped = false;
467 else if (*e == '\\')
468 escaped = true;
469 else if (*e == '\"')
470 break;
471 }
472
473 *l = e-current;
474 *state = *e == 0 ? e : e+1;
034c6ed7 475 } else {
0bab36f2
LP
476 for (e = current; *e; e++) {
477 if (escaped)
478 escaped = false;
479 else if (*e == '\\')
480 escaped = true;
481 else if (strchr(WHITESPACE, *e))
482 break;
483 }
484 *l = e-current;
485 *state = e;
034c6ed7
LP
486 }
487
488 return (char*) current;
489}
490
034c6ed7
LP
491int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
492 int r;
2fbe635a 493 _cleanup_fclose_ FILE *f = NULL;
20c03b7b 494 char fn[PATH_MAX], line[LINE_MAX], *p;
bb00e604 495 long unsigned ppid;
034c6ed7 496
8480e784 497 assert(pid > 0);
034c6ed7
LP
498 assert(_ppid);
499
bb00e604 500 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
8480e784 501 char_array_0(fn);
034c6ed7 502
2fbe635a
LP
503 f = fopen(fn, "re");
504 if (!f)
034c6ed7
LP
505 return -errno;
506
2fbe635a 507 if (!fgets(line, sizeof(line), f)) {
35d50f55 508 r = feof(f) ? -EIO : -errno;
034c6ed7
LP
509 fclose(f);
510 return r;
511 }
512
034c6ed7
LP
513 /* Let's skip the pid and comm fields. The latter is enclosed
514 * in () but does not escape any () in its value, so let's
515 * skip over it manually */
516
2fbe635a
LP
517 p = strrchr(line, ')');
518 if (!p)
034c6ed7
LP
519 return -EIO;
520
521 p++;
522
523 if (sscanf(p, " "
524 "%*c " /* state */
bb00e604 525 "%lu ", /* ppid */
034c6ed7
LP
526 &ppid) != 1)
527 return -EIO;
528
bb00e604 529 if ((long unsigned) (pid_t) ppid != ppid)
034c6ed7
LP
530 return -ERANGE;
531
532 *_ppid = (pid_t) ppid;
533
534 return 0;
535}
536
7640a5de 537int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
e67f47e5 538 _cleanup_fclose_ FILE *f = NULL;
7640a5de
LP
539 char fn[PATH_MAX], line[LINE_MAX], *p;
540
541 assert(pid > 0);
542 assert(st);
543
544 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
545 char_array_0(fn);
546
e67f47e5
LP
547 f = fopen(fn, "re");
548 if (!f)
7640a5de
LP
549 return -errno;
550
e67f47e5
LP
551 if (!fgets(line, sizeof(line), f)) {
552 if (ferror(f))
553 return -errno;
7640a5de 554
e67f47e5
LP
555 return -EIO;
556 }
7640a5de
LP
557
558 /* Let's skip the pid and comm fields. The latter is enclosed
559 * in () but does not escape any () in its value, so let's
560 * skip over it manually */
561
e67f47e5
LP
562 p = strrchr(line, ')');
563 if (!p)
7640a5de
LP
564 return -EIO;
565
566 p++;
567
568 if (sscanf(p, " "
569 "%*c " /* state */
570 "%*d " /* ppid */
571 "%*d " /* pgrp */
572 "%*d " /* session */
573 "%*d " /* tty_nr */
574 "%*d " /* tpgid */
575 "%*u " /* flags */
576 "%*u " /* minflt */
577 "%*u " /* cminflt */
578 "%*u " /* majflt */
579 "%*u " /* cmajflt */
580 "%*u " /* utime */
581 "%*u " /* stime */
582 "%*d " /* cutime */
583 "%*d " /* cstime */
584 "%*d " /* priority */
585 "%*d " /* nice */
586 "%*d " /* num_threads */
587 "%*d " /* itrealvalue */
588 "%llu " /* starttime */,
589 st) != 1)
590 return -EIO;
591
592 return 0;
593}
594
034c6ed7 595int write_one_line_file(const char *fn, const char *line) {
e67f47e5 596 _cleanup_fclose_ FILE *f = NULL;
034c6ed7
LP
597
598 assert(fn);
599 assert(line);
600
03ad1136
LP
601 f = fopen(fn, "we");
602 if (!f)
034c6ed7
LP
603 return -errno;
604
34ca941c 605 errno = 0;
e67f47e5
LP
606 if (fputs(line, f) < 0)
607 return errno ? -errno : -EIO;
034c6ed7 608
8e1bd70d
LP
609 if (!endswith(line, "\n"))
610 fputc('\n', f);
611
151b190e
LP
612 fflush(f);
613
e67f47e5
LP
614 if (ferror(f))
615 return errno ? -errno : -EIO;
151b190e 616
e67f47e5 617 return 0;
034c6ed7
LP
618}
619
34ca941c
LP
620int fchmod_umask(int fd, mode_t m) {
621 mode_t u;
622 int r;
623
624 u = umask(0777);
625 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
626 umask(u);
627
628 return r;
629}
630
631int write_one_line_file_atomic(const char *fn, const char *line) {
632 FILE *f;
633 int r;
634 char *p;
635
636 assert(fn);
637 assert(line);
638
639 r = fopen_temporary(fn, &f, &p);
640 if (r < 0)
641 return r;
642
643 fchmod_umask(fileno(f), 0644);
644
645 errno = 0;
646 if (fputs(line, f) < 0) {
647 r = -errno;
648 goto finish;
649 }
650
651 if (!endswith(line, "\n"))
652 fputc('\n', f);
653
654 fflush(f);
655
656 if (ferror(f)) {
657 if (errno != 0)
658 r = -errno;
659 else
660 r = -EIO;
661 } else {
662 if (rename(p, fn) < 0)
663 r = -errno;
664 else
665 r = 0;
666 }
667
668finish:
669 if (r < 0)
670 unlink(p);
671
672 fclose(f);
673 free(p);
674
675 return r;
676}
677
034c6ed7 678int read_one_line_file(const char *fn, char **line) {
2fbe635a 679 _cleanup_fclose_ FILE *f = NULL;
97c4a07d 680 char t[LINE_MAX], *c;
034c6ed7
LP
681
682 assert(fn);
683 assert(line);
684
4099a281
LP
685 f = fopen(fn, "re");
686 if (!f)
034c6ed7
LP
687 return -errno;
688
4099a281
LP
689 if (!fgets(t, sizeof(t), f)) {
690
2fbe635a 691 if (ferror(f))
e67f47e5 692 return errno ? -errno : -EIO;
4099a281
LP
693
694 t[0] = 0;
034c6ed7
LP
695 }
696
4099a281 697 c = strdup(t);
2fbe635a
LP
698 if (!c)
699 return -ENOMEM;
6f9a471a
LP
700 truncate_nl(c);
701
034c6ed7 702 *line = c;
2fbe635a 703 return 0;
034c6ed7 704}
44d8db9e 705
34ca941c 706int read_full_file(const char *fn, char **contents, size_t *size) {
2fbe635a 707 _cleanup_fclose_ FILE *f = NULL;
97c4a07d 708 size_t n, l;
2fbe635a 709 _cleanup_free_ char *buf = NULL;
97c4a07d
LP
710 struct stat st;
711
2fbe635a
LP
712 f = fopen(fn, "re");
713 if (!f)
97c4a07d
LP
714 return -errno;
715
2fbe635a
LP
716 if (fstat(fileno(f), &st) < 0)
717 return -errno;
97c4a07d 718
34ca941c 719 /* Safety check */
2fbe635a
LP
720 if (st.st_size > 4*1024*1024)
721 return -E2BIG;
34ca941c 722
97c4a07d
LP
723 n = st.st_size > 0 ? st.st_size : LINE_MAX;
724 l = 0;
725
726 for (;;) {
727 char *t;
728 size_t k;
729
2fbe635a
LP
730 t = realloc(buf, n+1);
731 if (!t)
732 return -ENOMEM;
97c4a07d
LP
733
734 buf = t;
735 k = fread(buf + l, 1, n - l, f);
736
737 if (k <= 0) {
2fbe635a
LP
738 if (ferror(f))
739 return -errno;
97c4a07d
LP
740
741 break;
742 }
743
744 l += k;
745 n *= 2;
746
747 /* Safety check */
2fbe635a
LP
748 if (n > 4*1024*1024)
749 return -E2BIG;
97c4a07d
LP
750 }
751
f8440af5 752 buf[l] = 0;
97c4a07d
LP
753 *contents = buf;
754 buf = NULL;
755
34ca941c
LP
756 if (size)
757 *size = l;
758
2fbe635a 759 return 0;
97c4a07d
LP
760}
761
762int parse_env_file(
763 const char *fname,
c899f8c6 764 const char *separator, ...) {
97c4a07d 765
ce8a6aa1 766 int r = 0;
44d91056 767 char *contents = NULL, *p;
97c4a07d
LP
768
769 assert(fname);
c899f8c6 770 assert(separator);
97c4a07d 771
34ca941c 772 if ((r = read_full_file(fname, &contents, NULL)) < 0)
97c4a07d
LP
773 return r;
774
775 p = contents;
776 for (;;) {
777 const char *key = NULL;
778
c899f8c6 779 p += strspn(p, separator);
97c4a07d
LP
780 p += strspn(p, WHITESPACE);
781
782 if (!*p)
783 break;
784
785 if (!strchr(COMMENTS, *p)) {
786 va_list ap;
787 char **value;
788
c899f8c6 789 va_start(ap, separator);
97c4a07d
LP
790 while ((key = va_arg(ap, char *))) {
791 size_t n;
792 char *v;
793
794 value = va_arg(ap, char **);
795
796 n = strlen(key);
797 if (strncmp(p, key, n) != 0 ||
798 p[n] != '=')
799 continue;
800
801 p += n + 1;
c899f8c6 802 n = strcspn(p, separator);
97c4a07d
LP
803
804 if (n >= 2 &&
e7db37dd
LP
805 strchr(QUOTES, p[0]) &&
806 p[n-1] == p[0])
97c4a07d
LP
807 v = strndup(p+1, n-2);
808 else
809 v = strndup(p, n);
810
811 if (!v) {
812 r = -ENOMEM;
813 va_end(ap);
814 goto fail;
815 }
816
dd36de4d
KS
817 if (v[0] == '\0') {
818 /* return empty value strings as NULL */
819 free(v);
820 v = NULL;
821 }
822
97c4a07d
LP
823 free(*value);
824 *value = v;
825
826 p += n;
ce8a6aa1
LP
827
828 r ++;
97c4a07d
LP
829 break;
830 }
831 va_end(ap);
832 }
833
834 if (!key)
c899f8c6 835 p += strcspn(p, separator);
97c4a07d
LP
836 }
837
97c4a07d
LP
838fail:
839 free(contents);
840 return r;
841}
842
8c7be95e
LP
843int load_env_file(
844 const char *fname,
845 char ***rl) {
846
847 FILE *f;
6a39419f 848 char **m = NULL;
8c7be95e
LP
849 int r;
850
851 assert(fname);
852 assert(rl);
853
854 if (!(f = fopen(fname, "re")))
855 return -errno;
856
857 while (!feof(f)) {
858 char l[LINE_MAX], *p, *u;
859 char **t;
860
861 if (!fgets(l, sizeof(l), f)) {
862 if (feof(f))
863 break;
864
865 r = -errno;
866 goto finish;
867 }
868
869 p = strstrip(l);
870
871 if (!*p)
872 continue;
873
874 if (strchr(COMMENTS, *p))
875 continue;
876
877 if (!(u = normalize_env_assignment(p))) {
0d0f0c50 878 r = log_oom();
8c7be95e
LP
879 goto finish;
880 }
881
882 t = strv_append(m, u);
883 free(u);
884
885 if (!t) {
0d0f0c50 886 r = log_oom();
8c7be95e
LP
887 goto finish;
888 }
889
890 strv_free(m);
891 m = t;
892 }
893
894 r = 0;
895
896 *rl = m;
897 m = NULL;
898
899finish:
900 if (f)
901 fclose(f);
902
903 strv_free(m);
904
905 return r;
906}
907
7640a5de 908int write_env_file(const char *fname, char **l) {
34ca941c 909 char **i, *p;
7640a5de
LP
910 FILE *f;
911 int r;
912
34ca941c
LP
913 r = fopen_temporary(fname, &f, &p);
914 if (r < 0)
915 return r;
7640a5de 916
34ca941c
LP
917 fchmod_umask(fileno(f), 0644);
918
919 errno = 0;
7640a5de
LP
920 STRV_FOREACH(i, l) {
921 fputs(*i, f);
922 fputc('\n', f);
923 }
924
925 fflush(f);
926
34ca941c
LP
927 if (ferror(f)) {
928 if (errno != 0)
929 r = -errno;
930 else
931 r = -EIO;
932 } else {
933 if (rename(p, fname) < 0)
934 r = -errno;
935 else
936 r = 0;
937 }
938
939 if (r < 0)
940 unlink(p);
941
7640a5de 942 fclose(f);
34ca941c 943 free(p);
7640a5de
LP
944
945 return r;
946}
947
7072ced8
LP
948char *truncate_nl(char *s) {
949 assert(s);
950
951 s[strcspn(s, NEWLINE)] = 0;
952 return s;
953}
954
87d2c1ff 955int get_process_comm(pid_t pid, char **name) {
7072ced8
LP
956 int r;
957
7072ced8
LP
958 assert(name);
959
87d2c1ff
LP
960 if (pid == 0)
961 r = read_one_line_file("/proc/self/comm", name);
962 else {
963 char *p;
964 if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
965 return -ENOMEM;
7072ced8 966
87d2c1ff
LP
967 r = read_one_line_file(p, name);
968 free(p);
969 }
7072ced8 970
87d2c1ff 971 return r;
7072ced8
LP
972}
973
87d2c1ff
LP
974int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
975 char *r, *k;
c59760ee
LP
976 int c;
977 bool space = false;
978 size_t left;
979 FILE *f;
980
c59760ee
LP
981 assert(max_length > 0);
982 assert(line);
983
87d2c1ff
LP
984 if (pid == 0)
985 f = fopen("/proc/self/cmdline", "re");
986 else {
987 char *p;
988 if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
989 return -ENOMEM;
c59760ee 990
87d2c1ff
LP
991 f = fopen(p, "re");
992 free(p);
993 }
c59760ee
LP
994
995 if (!f)
996 return -errno;
997
87d2c1ff
LP
998 r = new(char, max_length);
999 if (!r) {
c59760ee
LP
1000 fclose(f);
1001 return -ENOMEM;
1002 }
1003
1004 k = r;
1005 left = max_length;
1006 while ((c = getc(f)) != EOF) {
1007
1008 if (isprint(c)) {
1009 if (space) {
1010 if (left <= 4)
1011 break;
1012
1013 *(k++) = ' ';
057fbb58 1014 left--;
c59760ee
LP
1015 space = false;
1016 }
1017
1018 if (left <= 4)
1019 break;
1020
1021 *(k++) = (char) c;
057fbb58 1022 left--;
c59760ee
LP
1023 } else
1024 space = true;
1025 }
1026
1027 if (left <= 4) {
1028 size_t n = MIN(left-1, 3U);
1029 memcpy(k, "...", n);
1030 k[n] = 0;
1031 } else
1032 *k = 0;
1033
1034 fclose(f);
1035
35d2e7ec
LP
1036 /* Kernel threads have no argv[] */
1037 if (r[0] == 0) {
1038 char *t;
1039 int h;
1040
1041 free(r);
1042
87d2c1ff
LP
1043 if (!comm_fallback)
1044 return -ENOENT;
1045
1046 h = get_process_comm(pid, &t);
1047 if (h < 0)
35d2e7ec
LP
1048 return h;
1049
b7def684 1050 r = strjoin("[", t, "]", NULL);
35d2e7ec
LP
1051 free(t);
1052
87d2c1ff 1053 if (!r)
35d2e7ec
LP
1054 return -ENOMEM;
1055 }
fa776d8e 1056
c59760ee
LP
1057 *line = r;
1058 return 0;
1059}
1060
1e5678d0
LP
1061int is_kernel_thread(pid_t pid) {
1062 char *p;
1063 size_t count;
1064 char c;
1065 bool eof;
1066 FILE *f;
1067
1068 if (pid == 0)
1069 return 0;
1070
1071 if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1072 return -ENOMEM;
1073
1074 f = fopen(p, "re");
1075 free(p);
1076
1077 if (!f)
1078 return -errno;
1079
1080 count = fread(&c, 1, 1, f);
1081 eof = feof(f);
1082 fclose(f);
1083
1084 /* Kernel threads have an empty cmdline */
1085
1086 if (count <= 0)
1087 return eof ? 1 : -errno;
1088
1089 return 0;
1090}
1091
87d2c1ff
LP
1092int get_process_exe(pid_t pid, char **name) {
1093 int r;
1094
1095 assert(name);
1096
1097 if (pid == 0)
1098 r = readlink_malloc("/proc/self/exe", name);
1099 else {
1100 char *p;
1101 if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
1102 return -ENOMEM;
1103
1104 r = readlink_malloc(p, name);
1105 free(p);
1106 }
1107
1108 return r;
1109}
1110
901c3d0d 1111static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
7e4ab3c5
LP
1112 char *p;
1113 FILE *f;
1114 int r;
1115
1116 assert(uid);
1117
1118 if (pid == 0)
1119 return getuid();
1120
1121 if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
1122 return -ENOMEM;
1123
1124 f = fopen(p, "re");
1125 free(p);
1126
1127 if (!f)
1128 return -errno;
1129
1130 while (!feof(f)) {
1131 char line[LINE_MAX], *l;
1132
1133 if (!fgets(line, sizeof(line), f)) {
1134 if (feof(f))
1135 break;
1136
1137 r = -errno;
1138 goto finish;
1139 }
1140
1141 l = strstrip(line);
1142
901c3d0d
LP
1143 if (startswith(l, field)) {
1144 l += strlen(field);
7e4ab3c5
LP
1145 l += strspn(l, WHITESPACE);
1146
1147 l[strcspn(l, WHITESPACE)] = 0;
1148
1149 r = parse_uid(l, uid);
1150 goto finish;
1151 }
1152 }
1153
1154 r = -EIO;
1155
1156finish:
1157 fclose(f);
1158
1159 return r;
1160}
1161
901c3d0d
LP
1162int get_process_uid(pid_t pid, uid_t *uid) {
1163 return get_process_id(pid, "Uid:", uid);
1164}
1165
1166int get_process_gid(pid_t pid, gid_t *gid) {
1167 return get_process_id(pid, "Gid:", gid);
1168}
1169
fab56fc5
LP
1170char *strnappend(const char *s, const char *suffix, size_t b) {
1171 size_t a;
44d8db9e
LP
1172 char *r;
1173
fab56fc5
LP
1174 if (!s && !suffix)
1175 return strdup("");
1176
1177 if (!s)
1178 return strndup(suffix, b);
1179
1180 if (!suffix)
1181 return strdup(s);
1182
44d8db9e
LP
1183 assert(s);
1184 assert(suffix);
1185
1186 a = strlen(s);
aa408e77 1187 if (b > ((size_t) -1) - a)
040f18ea 1188 return NULL;
44d8db9e 1189
040f18ea
LP
1190 r = new(char, a+b+1);
1191 if (!r)
44d8db9e
LP
1192 return NULL;
1193
1194 memcpy(r, s, a);
1195 memcpy(r+a, suffix, b);
1196 r[a+b] = 0;
1197
1198 return r;
1199}
87f0e418 1200
fab56fc5
LP
1201char *strappend(const char *s, const char *suffix) {
1202 return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
1203}
1204
87f0e418
LP
1205int readlink_malloc(const char *p, char **r) {
1206 size_t l = 100;
1207
1208 assert(p);
1209 assert(r);
1210
1211 for (;;) {
1212 char *c;
1213 ssize_t n;
1214
1215 if (!(c = new(char, l)))
1216 return -ENOMEM;
1217
1218 if ((n = readlink(p, c, l-1)) < 0) {
1219 int ret = -errno;
1220 free(c);
1221 return ret;
1222 }
1223
1224 if ((size_t) n < l-1) {
1225 c[n] = 0;
1226 *r = c;
1227 return 0;
1228 }
1229
1230 free(c);
1231 l *= 2;
1232 }
1233}
1234
2c7108c4
LP
1235int readlink_and_make_absolute(const char *p, char **r) {
1236 char *target, *k;
1237 int j;
1238
1239 assert(p);
1240 assert(r);
1241
1242 if ((j = readlink_malloc(p, &target)) < 0)
1243 return j;
1244
1245 k = file_in_same_dir(p, target);
1246 free(target);
1247
1248 if (!k)
1249 return -ENOMEM;
1250
1251 *r = k;
1252 return 0;
1253}
1254
83096483
LP
1255int readlink_and_canonicalize(const char *p, char **r) {
1256 char *t, *s;
1257 int j;
1258
1259 assert(p);
1260 assert(r);
1261
1262 j = readlink_and_make_absolute(p, &t);
1263 if (j < 0)
1264 return j;
1265
1266 s = canonicalize_file_name(t);
1267 if (s) {
1268 free(t);
1269 *r = s;
1270 } else
1271 *r = t;
1272
1273 path_kill_slashes(*r);
1274
1275 return 0;
1276}
1277
2a987ee8
LP
1278int reset_all_signal_handlers(void) {
1279 int sig;
1280
1281 for (sig = 1; sig < _NSIG; sig++) {
1282 struct sigaction sa;
1283
1284 if (sig == SIGKILL || sig == SIGSTOP)
1285 continue;
1286
1287 zero(sa);
1288 sa.sa_handler = SIG_DFL;
431c32bf 1289 sa.sa_flags = SA_RESTART;
2a987ee8
LP
1290
1291 /* On Linux the first two RT signals are reserved by
1292 * glibc, and sigaction() will return EINVAL for them. */
1293 if ((sigaction(sig, &sa, NULL) < 0))
1294 if (errno != EINVAL)
1295 return -errno;
1296 }
1297
8e274523 1298 return 0;
2a987ee8 1299}
4a72ff34
LP
1300
1301char *strstrip(char *s) {
57a8eca8 1302 char *e;
4a72ff34
LP
1303
1304 /* Drops trailing whitespace. Modifies the string in
1305 * place. Returns pointer to first non-space character */
1306
1307 s += strspn(s, WHITESPACE);
1308
57a8eca8
LP
1309 for (e = strchr(s, 0); e > s; e --)
1310 if (!strchr(WHITESPACE, e[-1]))
1311 break;
4a72ff34 1312
57a8eca8 1313 *e = 0;
4a72ff34
LP
1314
1315 return s;
4a72ff34
LP
1316}
1317
ee9b5e01
LP
1318char *delete_chars(char *s, const char *bad) {
1319 char *f, *t;
1320
1321 /* Drops all whitespace, regardless where in the string */
1322
1323 for (f = s, t = s; *f; f++) {
1324 if (strchr(bad, *f))
1325 continue;
1326
1327 *(t++) = *f;
1328 }
1329
1330 *t = 0;
1331
1332 return s;
1333}
1334
ab1f0633
LP
1335bool in_charset(const char *s, const char* charset) {
1336 const char *i;
1337
1338 assert(s);
1339 assert(charset);
1340
1341 for (i = s; *i; i++)
1342 if (!strchr(charset, *i))
1343 return false;
1344
1345 return true;
1346}
1347
4a72ff34
LP
1348char *file_in_same_dir(const char *path, const char *filename) {
1349 char *e, *r;
1350 size_t k;
1351
1352 assert(path);
1353 assert(filename);
1354
1355 /* This removes the last component of path and appends
1356 * filename, unless the latter is absolute anyway or the
1357 * former isn't */
1358
1359 if (path_is_absolute(filename))
1360 return strdup(filename);
1361
1362 if (!(e = strrchr(path, '/')))
1363 return strdup(filename);
1364
1365 k = strlen(filename);
1366 if (!(r = new(char, e-path+1+k+1)))
1367 return NULL;
1368
1369 memcpy(r, path, e-path+1);
1370 memcpy(r+(e-path)+1, filename, k+1);
1371
1372 return r;
1373}
fb624d04 1374
c32dd69b
LP
1375int rmdir_parents(const char *path, const char *stop) {
1376 size_t l;
1377 int r = 0;
1378
1379 assert(path);
1380 assert(stop);
1381
1382 l = strlen(path);
1383
1384 /* Skip trailing slashes */
1385 while (l > 0 && path[l-1] == '/')
1386 l--;
1387
1388 while (l > 0) {
1389 char *t;
1390
1391 /* Skip last component */
1392 while (l > 0 && path[l-1] != '/')
1393 l--;
1394
1395 /* Skip trailing slashes */
1396 while (l > 0 && path[l-1] == '/')
1397 l--;
1398
1399 if (l <= 0)
1400 break;
1401
1402 if (!(t = strndup(path, l)))
1403 return -ENOMEM;
1404
1405 if (path_startswith(stop, t)) {
1406 free(t);
1407 return 0;
1408 }
1409
1410 r = rmdir(t);
1411 free(t);
1412
1413 if (r < 0)
1414 if (errno != ENOENT)
1415 return -errno;
1416 }
1417
1418 return 0;
1419}
1420
1421
fb624d04
LP
1422char hexchar(int x) {
1423 static const char table[16] = "0123456789abcdef";
1424
1425 return table[x & 15];
1426}
4fe88d28
LP
1427
1428int unhexchar(char c) {
1429
1430 if (c >= '0' && c <= '9')
1431 return c - '0';
1432
1433 if (c >= 'a' && c <= 'f')
ea430986 1434 return c - 'a' + 10;
4fe88d28
LP
1435
1436 if (c >= 'A' && c <= 'F')
ea430986 1437 return c - 'A' + 10;
4fe88d28
LP
1438
1439 return -1;
1440}
1441
1442char octchar(int x) {
1443 return '0' + (x & 7);
1444}
1445
1446int unoctchar(char c) {
1447
1448 if (c >= '0' && c <= '7')
1449 return c - '0';
1450
1451 return -1;
1452}
1453
5af98f82
LP
1454char decchar(int x) {
1455 return '0' + (x % 10);
1456}
1457
1458int undecchar(char c) {
1459
1460 if (c >= '0' && c <= '9')
1461 return c - '0';
1462
1463 return -1;
1464}
1465
4fe88d28
LP
1466char *cescape(const char *s) {
1467 char *r, *t;
1468 const char *f;
1469
1470 assert(s);
1471
1472 /* Does C style string escaping. */
1473
f8e2fb7b
LP
1474 r = new(char, strlen(s)*4 + 1);
1475 if (!r)
4fe88d28
LP
1476 return NULL;
1477
1478 for (f = s, t = r; *f; f++)
1479
1480 switch (*f) {
1481
1482 case '\a':
1483 *(t++) = '\\';
1484 *(t++) = 'a';
1485 break;
1486 case '\b':
1487 *(t++) = '\\';
1488 *(t++) = 'b';
1489 break;
1490 case '\f':
1491 *(t++) = '\\';
1492 *(t++) = 'f';
1493 break;
1494 case '\n':
1495 *(t++) = '\\';
1496 *(t++) = 'n';
1497 break;
1498 case '\r':
1499 *(t++) = '\\';
1500 *(t++) = 'r';
1501 break;
1502 case '\t':
1503 *(t++) = '\\';
1504 *(t++) = 't';
1505 break;
1506 case '\v':
1507 *(t++) = '\\';
1508 *(t++) = 'v';
1509 break;
1510 case '\\':
1511 *(t++) = '\\';
1512 *(t++) = '\\';
1513 break;
1514 case '"':
1515 *(t++) = '\\';
1516 *(t++) = '"';
1517 break;
1518 case '\'':
1519 *(t++) = '\\';
1520 *(t++) = '\'';
1521 break;
1522
1523 default:
1524 /* For special chars we prefer octal over
1525 * hexadecimal encoding, simply because glib's
1526 * g_strescape() does the same */
1527 if ((*f < ' ') || (*f >= 127)) {
1528 *(t++) = '\\';
1529 *(t++) = octchar((unsigned char) *f >> 6);
1530 *(t++) = octchar((unsigned char) *f >> 3);
1531 *(t++) = octchar((unsigned char) *f);
1532 } else
1533 *(t++) = *f;
1534 break;
1535 }
1536
1537 *t = 0;
1538
1539 return r;
1540}
1541
5b4c61cd 1542char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) {
4fe88d28
LP
1543 char *r, *t;
1544 const char *f;
5b4c61cd 1545 size_t pl;
4fe88d28
LP
1546
1547 assert(s);
1548
5b4c61cd
LP
1549 /* Undoes C style string escaping, and optionally prefixes it. */
1550
1551 pl = prefix ? strlen(prefix) : 0;
4fe88d28 1552
5b4c61cd 1553 r = new(char, pl+length+1);
7f110ff9 1554 if (!r)
4fe88d28
LP
1555 return r;
1556
5b4c61cd
LP
1557 if (prefix)
1558 memcpy(r, prefix, pl);
1559
1560 for (f = s, t = r + pl; f < s + length; f++) {
4fe88d28
LP
1561
1562 if (*f != '\\') {
1563 *(t++) = *f;
1564 continue;
1565 }
1566
1567 f++;
1568
1569 switch (*f) {
1570
1571 case 'a':
1572 *(t++) = '\a';
1573 break;
1574 case 'b':
1575 *(t++) = '\b';
1576 break;
1577 case 'f':
1578 *(t++) = '\f';
1579 break;
1580 case 'n':
1581 *(t++) = '\n';
1582 break;
1583 case 'r':
1584 *(t++) = '\r';
1585 break;
1586 case 't':
1587 *(t++) = '\t';
1588 break;
1589 case 'v':
1590 *(t++) = '\v';
1591 break;
1592 case '\\':
1593 *(t++) = '\\';
1594 break;
1595 case '"':
1596 *(t++) = '"';
1597 break;
1598 case '\'':
1599 *(t++) = '\'';
1600 break;
1601
e167fb86
LP
1602 case 's':
1603 /* This is an extension of the XDG syntax files */
1604 *(t++) = ' ';
1605 break;
1606
4fe88d28
LP
1607 case 'x': {
1608 /* hexadecimal encoding */
1609 int a, b;
1610
7f110ff9
LP
1611 a = unhexchar(f[1]);
1612 b = unhexchar(f[2]);
1613
1614 if (a < 0 || b < 0) {
4fe88d28
LP
1615 /* Invalid escape code, let's take it literal then */
1616 *(t++) = '\\';
1617 *(t++) = 'x';
1618 } else {
1619 *(t++) = (char) ((a << 4) | b);
1620 f += 2;
1621 }
1622
1623 break;
1624 }
1625
1626 case '0':
1627 case '1':
1628 case '2':
1629 case '3':
1630 case '4':
1631 case '5':
1632 case '6':
1633 case '7': {
1634 /* octal encoding */
1635 int a, b, c;
1636
7f110ff9
LP
1637 a = unoctchar(f[0]);
1638 b = unoctchar(f[1]);
1639 c = unoctchar(f[2]);
1640
1641 if (a < 0 || b < 0 || c < 0) {
4fe88d28
LP
1642 /* Invalid escape code, let's take it literal then */
1643 *(t++) = '\\';
1644 *(t++) = f[0];
1645 } else {
1646 *(t++) = (char) ((a << 6) | (b << 3) | c);
1647 f += 2;
1648 }
1649
1650 break;
1651 }
1652
1653 case 0:
1654 /* premature end of string.*/
1655 *(t++) = '\\';
1656 goto finish;
1657
1658 default:
1659 /* Invalid escape code, let's take it literal then */
1660 *(t++) = '\\';
f3d4cc01 1661 *(t++) = *f;
4fe88d28
LP
1662 break;
1663 }
1664 }
1665
1666finish:
1667 *t = 0;
1668 return r;
1669}
1670
5b4c61cd
LP
1671char *cunescape_length(const char *s, size_t length) {
1672 return cunescape_length_with_prefix(s, length, NULL);
1673}
1674
6febfd0d 1675char *cunescape(const char *s) {
5b4c61cd
LP
1676 assert(s);
1677
6febfd0d
LP
1678 return cunescape_length(s, strlen(s));
1679}
4fe88d28
LP
1680
1681char *xescape(const char *s, const char *bad) {
1682 char *r, *t;
1683 const char *f;
1684
1685 /* Escapes all chars in bad, in addition to \ and all special
1686 * chars, in \xFF style escaping. May be reversed with
1687 * cunescape. */
1688
1689 if (!(r = new(char, strlen(s)*4+1)))
1690 return NULL;
1691
1692 for (f = s, t = r; *f; f++) {
1693
b866264a
LP
1694 if ((*f < ' ') || (*f >= 127) ||
1695 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1696 *(t++) = '\\';
1697 *(t++) = 'x';
1698 *(t++) = hexchar(*f >> 4);
1699 *(t++) = hexchar(*f);
1700 } else
1701 *(t++) = *f;
1702 }
1703
1704 *t = 0;
1705
1706 return r;
1707}
1708
ea430986 1709char *bus_path_escape(const char *s) {
ea430986
LP
1710 char *r, *t;
1711 const char *f;
1712
47be870b
LP
1713 assert(s);
1714
ea430986
LP
1715 /* Escapes all chars that D-Bus' object path cannot deal
1716 * with. Can be reverse with bus_path_unescape() */
1717
1718 if (!(r = new(char, strlen(s)*3+1)))
1719 return NULL;
1720
1721 for (f = s, t = r; *f; f++) {
1722
1723 if (!(*f >= 'A' && *f <= 'Z') &&
1724 !(*f >= 'a' && *f <= 'z') &&
1725 !(*f >= '0' && *f <= '9')) {
1726 *(t++) = '_';
1727 *(t++) = hexchar(*f >> 4);
1728 *(t++) = hexchar(*f);
1729 } else
1730 *(t++) = *f;
1731 }
1732
1733 *t = 0;
1734
1735 return r;
1736}
1737
9e2f7c11 1738char *bus_path_unescape(const char *f) {
ea430986 1739 char *r, *t;
ea430986 1740
9e2f7c11 1741 assert(f);
47be870b 1742
9e2f7c11 1743 if (!(r = strdup(f)))
ea430986
LP
1744 return NULL;
1745
9e2f7c11 1746 for (t = r; *f; f++) {
ea430986
LP
1747
1748 if (*f == '_') {
1749 int a, b;
1750
1751 if ((a = unhexchar(f[1])) < 0 ||
1752 (b = unhexchar(f[2])) < 0) {
1753 /* Invalid escape code, let's take it literal then */
1754 *(t++) = '_';
1755 } else {
1756 *(t++) = (char) ((a << 4) | b);
1757 f += 2;
1758 }
1759 } else
1760 *(t++) = *f;
1761 }
1762
1763 *t = 0;
1764
1765 return r;
1766}
1767
67d51650 1768char *ascii_strlower(char *t) {
4fe88d28
LP
1769 char *p;
1770
67d51650 1771 assert(t);
4fe88d28 1772
67d51650 1773 for (p = t; *p; p++)
4fe88d28
LP
1774 if (*p >= 'A' && *p <= 'Z')
1775 *p = *p - 'A' + 'a';
1776
67d51650 1777 return t;
4fe88d28 1778}
1dccbe19 1779
a228a22f 1780static bool ignore_file_allow_backup(const char *filename) {
c85dc17b
LP
1781 assert(filename);
1782
1783 return
1784 filename[0] == '.' ||
6c78be3c 1785 streq(filename, "lost+found") ||
e472d476
LP
1786 streq(filename, "aquota.user") ||
1787 streq(filename, "aquota.group") ||
c85dc17b
LP
1788 endswith(filename, ".rpmnew") ||
1789 endswith(filename, ".rpmsave") ||
1790 endswith(filename, ".rpmorig") ||
1791 endswith(filename, ".dpkg-old") ||
1792 endswith(filename, ".dpkg-new") ||
1793 endswith(filename, ".swp");
1794}
1795
a228a22f
LP
1796bool ignore_file(const char *filename) {
1797 assert(filename);
1798
1799 if (endswith(filename, "~"))
1800 return false;
1801
1802 return ignore_file_allow_backup(filename);
1803}
1804
3a0ecb08
LP
1805int fd_nonblock(int fd, bool nonblock) {
1806 int flags;
1807
1808 assert(fd >= 0);
1809
1810 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1811 return -errno;
1812
1813 if (nonblock)
1814 flags |= O_NONBLOCK;
1815 else
1816 flags &= ~O_NONBLOCK;
1817
1818 if (fcntl(fd, F_SETFL, flags) < 0)
1819 return -errno;
1820
1821 return 0;
1822}
1823
1824int fd_cloexec(int fd, bool cloexec) {
1825 int flags;
1826
1827 assert(fd >= 0);
1828
1829 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1830 return -errno;
1831
1832 if (cloexec)
1833 flags |= FD_CLOEXEC;
1834 else
1835 flags &= ~FD_CLOEXEC;
1836
1837 if (fcntl(fd, F_SETFD, flags) < 0)
1838 return -errno;
1839
1840 return 0;
1841}
1842
b19be9eb
LP
1843static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
1844 unsigned i;
1845
1846 assert(n_fdset == 0 || fdset);
1847
1848 for (i = 0; i < n_fdset; i++)
1849 if (fdset[i] == fd)
1850 return true;
1851
1852 return false;
1853}
1854
a0d40ac5
LP
1855int close_all_fds(const int except[], unsigned n_except) {
1856 DIR *d;
1857 struct dirent *de;
1858 int r = 0;
1859
b19be9eb
LP
1860 assert(n_except == 0 || except);
1861
1862 d = opendir("/proc/self/fd");
1863 if (!d) {
1864 int fd;
1865 struct rlimit rl;
1866
1867 /* When /proc isn't available (for example in chroots)
1868 * the fallback is brute forcing through the fd
1869 * table */
1870
1871 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
1872 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
1873
1874 if (fd_in_set(fd, except, n_except))
1875 continue;
1876
1877 if (close_nointr(fd) < 0)
1878 if (errno != EBADF && r == 0)
1879 r = -errno;
1880 }
1881
1882 return r;
1883 }
a0d40ac5
LP
1884
1885 while ((de = readdir(d))) {
a7610064 1886 int fd = -1;
a0d40ac5 1887
a16e1123 1888 if (ignore_file(de->d_name))
a0d40ac5
LP
1889 continue;
1890
720ce21d
LP
1891 if (safe_atoi(de->d_name, &fd) < 0)
1892 /* Let's better ignore this, just in case */
1893 continue;
a0d40ac5
LP
1894
1895 if (fd < 3)
1896 continue;
1897
1898 if (fd == dirfd(d))
1899 continue;
1900
b19be9eb
LP
1901 if (fd_in_set(fd, except, n_except))
1902 continue;
a0d40ac5 1903
720ce21d 1904 if (close_nointr(fd) < 0) {
2f357920 1905 /* Valgrind has its own FD and doesn't want to have it closed */
720ce21d
LP
1906 if (errno != EBADF && r == 0)
1907 r = -errno;
2f357920 1908 }
a0d40ac5
LP
1909 }
1910
a0d40ac5
LP
1911 closedir(d);
1912 return r;
1913}
1914
db12775d
LP
1915bool chars_intersect(const char *a, const char *b) {
1916 const char *p;
1917
1918 /* Returns true if any of the chars in a are in b. */
1919 for (p = a; *p; p++)
1920 if (strchr(b, *p))
1921 return true;
1922
1923 return false;
1924}
1925
8b6c7120
LP
1926char *format_timestamp(char *buf, size_t l, usec_t t) {
1927 struct tm tm;
1928 time_t sec;
1929
1930 assert(buf);
1931 assert(l > 0);
1932
1933 if (t <= 0)
1934 return NULL;
1935
f872ec33 1936 sec = (time_t) (t / USEC_PER_SEC);
8b6c7120
LP
1937
1938 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1939 return NULL;
1940
1941 return buf;
1942}
1943
584be568
LP
1944char *format_timestamp_pretty(char *buf, size_t l, usec_t t) {
1945 usec_t n, d;
1946
1947 n = now(CLOCK_REALTIME);
1948
1949 if (t <= 0 || t > n || t + USEC_PER_DAY*7 <= t)
1950 return NULL;
1951
1952 d = n - t;
1953
1954 if (d >= USEC_PER_YEAR)
1955 snprintf(buf, l, "%llu years and %llu months ago",
1956 (unsigned long long) (d / USEC_PER_YEAR),
1957 (unsigned long long) ((d % USEC_PER_YEAR) / USEC_PER_MONTH));
1958 else if (d >= USEC_PER_MONTH)
1959 snprintf(buf, l, "%llu months and %llu days ago",
1960 (unsigned long long) (d / USEC_PER_MONTH),
1961 (unsigned long long) ((d % USEC_PER_MONTH) / USEC_PER_DAY));
1962 else if (d >= USEC_PER_WEEK)
1963 snprintf(buf, l, "%llu weeks and %llu days ago",
1964 (unsigned long long) (d / USEC_PER_WEEK),
1965 (unsigned long long) ((d % USEC_PER_WEEK) / USEC_PER_DAY));
1966 else if (d >= 2*USEC_PER_DAY)
1967 snprintf(buf, l, "%llu days ago", (unsigned long long) (d / USEC_PER_DAY));
1968 else if (d >= 25*USEC_PER_HOUR)
1969 snprintf(buf, l, "1 day and %lluh ago",
1970 (unsigned long long) ((d - USEC_PER_DAY) / USEC_PER_HOUR));
1971 else if (d >= 6*USEC_PER_HOUR)
1972 snprintf(buf, l, "%lluh ago",
1973 (unsigned long long) (d / USEC_PER_HOUR));
1974 else if (d >= USEC_PER_HOUR)
1975 snprintf(buf, l, "%lluh %llumin ago",
1976 (unsigned long long) (d / USEC_PER_HOUR),
1977 (unsigned long long) ((d % USEC_PER_HOUR) / USEC_PER_MINUTE));
1978 else if (d >= 5*USEC_PER_MINUTE)
1979 snprintf(buf, l, "%llumin ago",
1980 (unsigned long long) (d / USEC_PER_MINUTE));
1981 else if (d >= USEC_PER_MINUTE)
1982 snprintf(buf, l, "%llumin %llus ago",
1983 (unsigned long long) (d / USEC_PER_MINUTE),
1984 (unsigned long long) ((d % USEC_PER_MINUTE) / USEC_PER_SEC));
1985 else if (d >= USEC_PER_SEC)
1986 snprintf(buf, l, "%llus ago",
1987 (unsigned long long) (d / USEC_PER_SEC));
1988 else if (d >= USEC_PER_MSEC)
1989 snprintf(buf, l, "%llums ago",
1990 (unsigned long long) (d / USEC_PER_MSEC));
1991 else if (d > 0)
1992 snprintf(buf, l, "%lluus ago",
1993 (unsigned long long) d);
1994 else
1995 snprintf(buf, l, "now");
1996
1997 buf[l-1] = 0;
1998 return buf;
1999}
2000
871d7de4
LP
2001char *format_timespan(char *buf, size_t l, usec_t t) {
2002 static const struct {
2003 const char *suffix;
2004 usec_t usec;
2005 } table[] = {
2006 { "w", USEC_PER_WEEK },
2007 { "d", USEC_PER_DAY },
2008 { "h", USEC_PER_HOUR },
2009 { "min", USEC_PER_MINUTE },
2010 { "s", USEC_PER_SEC },
2011 { "ms", USEC_PER_MSEC },
2012 { "us", 1 },
2013 };
2014
2015 unsigned i;
2016 char *p = buf;
2017
2018 assert(buf);
2019 assert(l > 0);
2020
2021 if (t == (usec_t) -1)
2022 return NULL;
2023
4502d22c
LP
2024 if (t == 0) {
2025 snprintf(p, l, "0");
2026 p[l-1] = 0;
2027 return p;
2028 }
2029
871d7de4
LP
2030 /* The result of this function can be parsed with parse_usec */
2031
2032 for (i = 0; i < ELEMENTSOF(table); i++) {
2033 int k;
2034 size_t n;
2035
2036 if (t < table[i].usec)
2037 continue;
2038
2039 if (l <= 1)
2040 break;
2041
2042 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
2043 n = MIN((size_t) k, l);
2044
2045 l -= n;
2046 p += n;
2047
2048 t %= table[i].usec;
2049 }
2050
2051 *p = 0;
2052
2053 return buf;
2054}
2055
42856c10 2056bool fstype_is_network(const char *fstype) {
a05f97b3
LP
2057 static const char table[] =
2058 "cifs\0"
2059 "smbfs\0"
2060 "ncpfs\0"
2061 "nfs\0"
2062 "nfs4\0"
2063 "gfs\0"
73836c5c 2064 "gfs2\0";
42856c10 2065
a05f97b3 2066 return nulstr_contains(table, fstype);
42856c10
LP
2067}
2068
601f6a1e 2069int chvt(int vt) {
a05f97b3 2070 _cleanup_close_ int fd;
601f6a1e 2071
a05f97b3
LP
2072 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
2073 if (fd < 0)
601f6a1e
LP
2074 return -errno;
2075
2076 if (vt < 0) {
2077 int tiocl[2] = {
2078 TIOCL_GETKMSGREDIRECT,
2079 0
2080 };
2081
a05f97b3
LP
2082 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
2083 return -errno;
601f6a1e
LP
2084
2085 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
2086 }
2087
2088 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
a05f97b3 2089 return -errno;
601f6a1e 2090
a05f97b3 2091 return 0;
601f6a1e
LP
2092}
2093
8f2d43a0 2094int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
80876c20
LP
2095 struct termios old_termios, new_termios;
2096 char c;
20c03b7b 2097 char line[LINE_MAX];
80876c20
LP
2098
2099 assert(f);
2100 assert(ret);
2101
2102 if (tcgetattr(fileno(f), &old_termios) >= 0) {
2103 new_termios = old_termios;
2104
2105 new_termios.c_lflag &= ~ICANON;
2106 new_termios.c_cc[VMIN] = 1;
2107 new_termios.c_cc[VTIME] = 0;
2108
2109 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
2110 size_t k;
2111
8f2d43a0
LP
2112 if (t != (usec_t) -1) {
2113 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
2114 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
2115 return -ETIMEDOUT;
2116 }
2117 }
2118
80876c20
LP
2119 k = fread(&c, 1, 1, f);
2120
2121 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
2122
2123 if (k <= 0)
2124 return -EIO;
2125
2126 if (need_nl)
2127 *need_nl = c != '\n';
2128
2129 *ret = c;
2130 return 0;
2131 }
2132 }
2133
8f2d43a0
LP
2134 if (t != (usec_t) -1)
2135 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
2136 return -ETIMEDOUT;
2137
2138 if (!fgets(line, sizeof(line), f))
80876c20
LP
2139 return -EIO;
2140
2141 truncate_nl(line);
2142
2143 if (strlen(line) != 1)
2144 return -EBADMSG;
2145
2146 if (need_nl)
2147 *need_nl = false;
2148
2149 *ret = line[0];
2150 return 0;
2151}
2152
2153int ask(char *ret, const char *replies, const char *text, ...) {
1b39d4b9
LP
2154 bool on_tty;
2155
80876c20
LP
2156 assert(ret);
2157 assert(replies);
2158 assert(text);
2159
1b39d4b9
LP
2160 on_tty = isatty(STDOUT_FILENO);
2161
80876c20
LP
2162 for (;;) {
2163 va_list ap;
2164 char c;
2165 int r;
2166 bool need_nl = true;
2167
1b39d4b9 2168 if (on_tty)
c1072ea0 2169 fputs(ANSI_HIGHLIGHT_ON, stdout);
b1b2dc0c 2170
80876c20
LP
2171 va_start(ap, text);
2172 vprintf(text, ap);
2173 va_end(ap);
2174
1b39d4b9 2175 if (on_tty)
c1072ea0 2176 fputs(ANSI_HIGHLIGHT_OFF, stdout);
b1b2dc0c 2177
80876c20
LP
2178 fflush(stdout);
2179
8f2d43a0
LP
2180 r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
2181 if (r < 0) {
80876c20
LP
2182
2183 if (r == -EBADMSG) {
2184 puts("Bad input, please try again.");
2185 continue;
2186 }
2187
2188 putchar('\n');
2189 return r;
2190 }
2191
2192 if (need_nl)
2193 putchar('\n');
2194
2195 if (strchr(replies, c)) {
2196 *ret = c;
2197 return 0;
2198 }
2199
2200 puts("Read unexpected character, please try again.");
2201 }
2202}
2203
512947d4 2204int reset_terminal_fd(int fd, bool switch_to_text) {
80876c20
LP
2205 struct termios termios;
2206 int r = 0;
3fe5e5d4
LP
2207
2208 /* Set terminal to some sane defaults */
80876c20
LP
2209
2210 assert(fd >= 0);
2211
eed1d0e3
LP
2212 /* We leave locked terminal attributes untouched, so that
2213 * Plymouth may set whatever it wants to set, and we don't
2214 * interfere with that. */
3fe5e5d4
LP
2215
2216 /* Disable exclusive mode, just in case */
2217 ioctl(fd, TIOCNXCL);
2218
5c0100a5 2219 /* Switch to text mode */
512947d4
MS
2220 if (switch_to_text)
2221 ioctl(fd, KDSETMODE, KD_TEXT);
5c0100a5 2222
3fe5e5d4 2223 /* Enable console unicode mode */
df465b3f 2224 ioctl(fd, KDSKBMODE, K_UNICODE);
80876c20
LP
2225
2226 if (tcgetattr(fd, &termios) < 0) {
2227 r = -errno;
2228 goto finish;
2229 }
2230
aaf694ca
LP
2231 /* We only reset the stuff that matters to the software. How
2232 * hardware is set up we don't touch assuming that somebody
2233 * else will do that for us */
2234
2235 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
2236 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
2237 termios.c_oflag |= ONLCR;
2238 termios.c_cflag |= CREAD;
2239 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
2240
2241 termios.c_cc[VINTR] = 03; /* ^C */
2242 termios.c_cc[VQUIT] = 034; /* ^\ */
2243 termios.c_cc[VERASE] = 0177;
2244 termios.c_cc[VKILL] = 025; /* ^X */
2245 termios.c_cc[VEOF] = 04; /* ^D */
2246 termios.c_cc[VSTART] = 021; /* ^Q */
2247 termios.c_cc[VSTOP] = 023; /* ^S */
2248 termios.c_cc[VSUSP] = 032; /* ^Z */
2249 termios.c_cc[VLNEXT] = 026; /* ^V */
2250 termios.c_cc[VWERASE] = 027; /* ^W */
2251 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
2252 termios.c_cc[VEOL] = 0;
2253 termios.c_cc[VEOL2] = 0;
80876c20
LP
2254
2255 termios.c_cc[VTIME] = 0;
2256 termios.c_cc[VMIN] = 1;
2257
2258 if (tcsetattr(fd, TCSANOW, &termios) < 0)
2259 r = -errno;
2260
2261finish:
2262 /* Just in case, flush all crap out */
2263 tcflush(fd, TCIOFLUSH);
2264
2265 return r;
2266}
2267
6ea832a2
LP
2268int reset_terminal(const char *name) {
2269 int fd, r;
2270
2271 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
2272 if (fd < 0)
2273 return fd;
2274
512947d4 2275 r = reset_terminal_fd(fd, true);
6ea832a2
LP
2276 close_nointr_nofail(fd);
2277
2278 return r;
2279}
2280
80876c20
LP
2281int open_terminal(const char *name, int mode) {
2282 int fd, r;
f73f76ac 2283 unsigned c = 0;
80876c20 2284
f73f76ac
LP
2285 /*
2286 * If a TTY is in the process of being closed opening it might
2287 * cause EIO. This is horribly awful, but unlikely to be
2288 * changed in the kernel. Hence we work around this problem by
2289 * retrying a couple of times.
2290 *
2291 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
2292 */
2293
2294 for (;;) {
af6da548
LP
2295 fd = open(name, mode);
2296 if (fd >= 0)
f73f76ac
LP
2297 break;
2298
2299 if (errno != EIO)
2300 return -errno;
2301
af6da548 2302 /* Max 1s in total */
f73f76ac
LP
2303 if (c >= 20)
2304 return -errno;
2305
2306 usleep(50 * USEC_PER_MSEC);
2307 c++;
2308 }
2309
2310 if (fd < 0)
80876c20
LP
2311 return -errno;
2312
af6da548
LP
2313 r = isatty(fd);
2314 if (r < 0) {
80876c20
LP
2315 close_nointr_nofail(fd);
2316 return -errno;
2317 }
2318
2319 if (!r) {
2320 close_nointr_nofail(fd);
2321 return -ENOTTY;
2322 }
2323
2324 return fd;
2325}
2326
2327int flush_fd(int fd) {
2328 struct pollfd pollfd;
2329
2330 zero(pollfd);
2331 pollfd.fd = fd;
2332 pollfd.events = POLLIN;
2333
2334 for (;;) {
20c03b7b 2335 char buf[LINE_MAX];
80876c20
LP
2336 ssize_t l;
2337 int r;
2338
2339 if ((r = poll(&pollfd, 1, 0)) < 0) {
2340
2341 if (errno == EINTR)
2342 continue;
2343
2344 return -errno;
2345 }
2346
2347 if (r == 0)
2348 return 0;
2349
2350 if ((l = read(fd, buf, sizeof(buf))) < 0) {
2351
2352 if (errno == EINTR)
2353 continue;
2354
2355 if (errno == EAGAIN)
2356 return 0;
2357
2358 return -errno;
2359 }
2360
2361 if (l <= 0)
2362 return 0;
2363 }
2364}
2365
af6da548
LP
2366int acquire_terminal(
2367 const char *name,
2368 bool fail,
2369 bool force,
2370 bool ignore_tiocstty_eperm,
2371 usec_t timeout) {
2372
4a0ff478 2373 int fd = -1, notify = -1, r = 0, wd = -1;
af6da548 2374 usec_t ts = 0;
32c4bef8 2375 struct sigaction sa_old, sa_new;
80876c20
LP
2376
2377 assert(name);
2378
2379 /* We use inotify to be notified when the tty is closed. We
2380 * create the watch before checking if we can actually acquire
2381 * it, so that we don't lose any event.
2382 *
2383 * Note: strictly speaking this actually watches for the
2384 * device being closed, it does *not* really watch whether a
2385 * tty loses its controlling process. However, unless some
2386 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
2387 * its tty otherwise this will not become a problem. As long
2388 * as the administrator makes sure not configure any service
2389 * on the same tty as an untrusted user this should not be a
2390 * problem. (Which he probably should not do anyway.) */
2391
af6da548
LP
2392 if (timeout != (usec_t) -1)
2393 ts = now(CLOCK_MONOTONIC);
2394
80876c20 2395 if (!fail && !force) {
af6da548
LP
2396 notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
2397 if (notify < 0) {
80876c20
LP
2398 r = -errno;
2399 goto fail;
2400 }
2401
af6da548
LP
2402 wd = inotify_add_watch(notify, name, IN_CLOSE);
2403 if (wd < 0) {
80876c20
LP
2404 r = -errno;
2405 goto fail;
2406 }
2407 }
2408
2409 for (;;) {
af6da548
LP
2410 if (notify >= 0) {
2411 r = flush_fd(notify);
2412 if (r < 0)
e3d1855b 2413 goto fail;
af6da548 2414 }
80876c20
LP
2415
2416 /* We pass here O_NOCTTY only so that we can check the return
2417 * value TIOCSCTTY and have a reliable way to figure out if we
2418 * successfully became the controlling process of the tty */
af6da548
LP
2419 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
2420 if (fd < 0)
6ea832a2 2421 return fd;
80876c20 2422
32c4bef8
LP
2423 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2424 * if we already own the tty. */
2425 zero(sa_new);
2426 sa_new.sa_handler = SIG_IGN;
2427 sa_new.sa_flags = SA_RESTART;
2428 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2429
80876c20 2430 /* First, try to get the tty */
32c4bef8
LP
2431 if (ioctl(fd, TIOCSCTTY, force) < 0)
2432 r = -errno;
2433
2434 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
21de3988
LP
2435
2436 /* Sometimes it makes sense to ignore TIOCSCTTY
2437 * returning EPERM, i.e. when very likely we already
2438 * are have this controlling terminal. */
32c4bef8 2439 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
21de3988
LP
2440 r = 0;
2441
32c4bef8 2442 if (r < 0 && (force || fail || r != -EPERM)) {
80876c20
LP
2443 goto fail;
2444 }
2445
2446 if (r >= 0)
2447 break;
2448
2449 assert(!fail);
2450 assert(!force);
2451 assert(notify >= 0);
2452
2453 for (;;) {
f601daa7 2454 uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
80876c20 2455 ssize_t l;
f601daa7 2456 struct inotify_event *e;
80876c20 2457
af6da548
LP
2458 if (timeout != (usec_t) -1) {
2459 usec_t n;
2460
2461 n = now(CLOCK_MONOTONIC);
2462 if (ts + timeout < n) {
2463 r = -ETIMEDOUT;
2464 goto fail;
2465 }
2466
2467 r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
2468 if (r < 0)
2469 goto fail;
2470
2471 if (r == 0) {
2472 r = -ETIMEDOUT;
2473 goto fail;
2474 }
2475 }
2476
2477 l = read(notify, inotify_buffer, sizeof(inotify_buffer));
2478 if (l < 0) {
80876c20 2479
af6da548 2480 if (errno == EINTR || errno == EAGAIN)
f601daa7
LP
2481 continue;
2482
2483 r = -errno;
2484 goto fail;
2485 }
2486
2487 e = (struct inotify_event*) inotify_buffer;
80876c20 2488
f601daa7
LP
2489 while (l > 0) {
2490 size_t step;
80876c20 2491
f601daa7 2492 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
80876c20 2493 r = -EIO;
f601daa7
LP
2494 goto fail;
2495 }
80876c20 2496
f601daa7
LP
2497 step = sizeof(struct inotify_event) + e->len;
2498 assert(step <= (size_t) l);
80876c20 2499
f601daa7
LP
2500 e = (struct inotify_event*) ((uint8_t*) e + step);
2501 l -= step;
80876c20
LP
2502 }
2503
2504 break;
2505 }
2506
2507 /* We close the tty fd here since if the old session
2508 * ended our handle will be dead. It's important that
2509 * we do this after sleeping, so that we don't enter
2510 * an endless loop. */
2511 close_nointr_nofail(fd);
2512 }
2513
2514 if (notify >= 0)
a16e1123 2515 close_nointr_nofail(notify);
80876c20 2516
512947d4
MS
2517 r = reset_terminal_fd(fd, true);
2518 if (r < 0)
80876c20
LP
2519 log_warning("Failed to reset terminal: %s", strerror(-r));
2520
2521 return fd;
2522
2523fail:
2524 if (fd >= 0)
a16e1123 2525 close_nointr_nofail(fd);
80876c20
LP
2526
2527 if (notify >= 0)
a16e1123 2528 close_nointr_nofail(notify);
80876c20
LP
2529
2530 return r;
2531}
2532
2533int release_terminal(void) {
2534 int r = 0, fd;
57cd2192 2535 struct sigaction sa_old, sa_new;
80876c20 2536
ccaa6149 2537 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
80876c20
LP
2538 return -errno;
2539
57cd2192
LP
2540 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2541 * by our own TIOCNOTTY */
2542
2543 zero(sa_new);
2544 sa_new.sa_handler = SIG_IGN;
2545 sa_new.sa_flags = SA_RESTART;
2546 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2547
80876c20
LP
2548 if (ioctl(fd, TIOCNOTTY) < 0)
2549 r = -errno;
2550
57cd2192
LP
2551 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
2552
80876c20
LP
2553 close_nointr_nofail(fd);
2554 return r;
2555}
2556
9a34ec5f
LP
2557int sigaction_many(const struct sigaction *sa, ...) {
2558 va_list ap;
2559 int r = 0, sig;
2560
2561 va_start(ap, sa);
2562 while ((sig = va_arg(ap, int)) > 0)
2563 if (sigaction(sig, sa, NULL) < 0)
2564 r = -errno;
2565 va_end(ap);
2566
2567 return r;
2568}
2569
2570int ignore_signals(int sig, ...) {
a337c6fc 2571 struct sigaction sa;
9a34ec5f
LP
2572 va_list ap;
2573 int r = 0;
a337c6fc
LP
2574
2575 zero(sa);
2576 sa.sa_handler = SIG_IGN;
2577 sa.sa_flags = SA_RESTART;
2578
9a34ec5f
LP
2579 if (sigaction(sig, &sa, NULL) < 0)
2580 r = -errno;
2581
2582 va_start(ap, sig);
2583 while ((sig = va_arg(ap, int)) > 0)
2584 if (sigaction(sig, &sa, NULL) < 0)
2585 r = -errno;
2586 va_end(ap);
2587
2588 return r;
2589}
2590
2591int default_signals(int sig, ...) {
2592 struct sigaction sa;
2593 va_list ap;
2594 int r = 0;
2595
2596 zero(sa);
2597 sa.sa_handler = SIG_DFL;
2598 sa.sa_flags = SA_RESTART;
2599
2600 if (sigaction(sig, &sa, NULL) < 0)
2601 r = -errno;
2602
2603 va_start(ap, sig);
2604 while ((sig = va_arg(ap, int)) > 0)
2605 if (sigaction(sig, &sa, NULL) < 0)
2606 r = -errno;
2607 va_end(ap);
2608
2609 return r;
a337c6fc
LP
2610}
2611
8d567588
LP
2612int close_pipe(int p[]) {
2613 int a = 0, b = 0;
2614
2615 assert(p);
2616
2617 if (p[0] >= 0) {
2618 a = close_nointr(p[0]);
2619 p[0] = -1;
2620 }
2621
2622 if (p[1] >= 0) {
2623 b = close_nointr(p[1]);
2624 p[1] = -1;
2625 }
2626
2627 return a < 0 ? a : b;
2628}
2629
eb22ac37 2630ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
8d567588
LP
2631 uint8_t *p;
2632 ssize_t n = 0;
2633
2634 assert(fd >= 0);
2635 assert(buf);
2636
2637 p = buf;
2638
2639 while (nbytes > 0) {
2640 ssize_t k;
2641
2642 if ((k = read(fd, p, nbytes)) <= 0) {
2643
eb22ac37 2644 if (k < 0 && errno == EINTR)
8d567588
LP
2645 continue;
2646
eb22ac37 2647 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588
LP
2648 struct pollfd pollfd;
2649
2650 zero(pollfd);
2651 pollfd.fd = fd;
2652 pollfd.events = POLLIN;
2653
2654 if (poll(&pollfd, 1, -1) < 0) {
2655 if (errno == EINTR)
2656 continue;
2657
2658 return n > 0 ? n : -errno;
2659 }
2660
2661 if (pollfd.revents != POLLIN)
2662 return n > 0 ? n : -EIO;
2663
2664 continue;
2665 }
2666
2667 return n > 0 ? n : (k < 0 ? -errno : 0);
2668 }
2669
2670 p += k;
2671 nbytes -= k;
2672 n += k;
2673 }
2674
2675 return n;
2676}
2677
eb22ac37
LP
2678ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2679 const uint8_t *p;
2680 ssize_t n = 0;
2681
2682 assert(fd >= 0);
2683 assert(buf);
2684
2685 p = buf;
2686
2687 while (nbytes > 0) {
2688 ssize_t k;
2689
fe652127
LP
2690 k = write(fd, p, nbytes);
2691 if (k <= 0) {
eb22ac37
LP
2692
2693 if (k < 0 && errno == EINTR)
2694 continue;
2695
2696 if (k < 0 && errno == EAGAIN && do_poll) {
2697 struct pollfd pollfd;
2698
2699 zero(pollfd);
2700 pollfd.fd = fd;
2701 pollfd.events = POLLOUT;
2702
2703 if (poll(&pollfd, 1, -1) < 0) {
2704 if (errno == EINTR)
2705 continue;
2706
2707 return n > 0 ? n : -errno;
2708 }
2709
2710 if (pollfd.revents != POLLOUT)
2711 return n > 0 ? n : -EIO;
2712
2713 continue;
2714 }
2715
2716 return n > 0 ? n : (k < 0 ? -errno : 0);
2717 }
2718
2719 p += k;
2720 nbytes -= k;
2721 n += k;
2722 }
2723
2724 return n;
2725}
2726
24a6e4a4
LP
2727int parse_usec(const char *t, usec_t *usec) {
2728 static const struct {
2729 const char *suffix;
2730 usec_t usec;
2731 } table[] = {
2732 { "sec", USEC_PER_SEC },
2733 { "s", USEC_PER_SEC },
2734 { "min", USEC_PER_MINUTE },
2735 { "hr", USEC_PER_HOUR },
2736 { "h", USEC_PER_HOUR },
2737 { "d", USEC_PER_DAY },
2738 { "w", USEC_PER_WEEK },
2739 { "msec", USEC_PER_MSEC },
2740 { "ms", USEC_PER_MSEC },
2741 { "m", USEC_PER_MINUTE },
2742 { "usec", 1ULL },
2743 { "us", 1ULL },
d88a251b 2744 { "", USEC_PER_SEC }, /* default is sec */
24a6e4a4
LP
2745 };
2746
2747 const char *p;
2748 usec_t r = 0;
2749
2750 assert(t);
2751 assert(usec);
2752
2753 p = t;
2754 do {
2755 long long l;
2756 char *e;
2757 unsigned i;
2758
2759 errno = 0;
2760 l = strtoll(p, &e, 10);
2761
2762 if (errno != 0)
2763 return -errno;
2764
2765 if (l < 0)
2766 return -ERANGE;
2767
2768 if (e == p)
2769 return -EINVAL;
2770
2771 e += strspn(e, WHITESPACE);
2772
2773 for (i = 0; i < ELEMENTSOF(table); i++)
2774 if (startswith(e, table[i].suffix)) {
2775 r += (usec_t) l * table[i].usec;
2776 p = e + strlen(table[i].suffix);
2777 break;
2778 }
2779
2780 if (i >= ELEMENTSOF(table))
2781 return -EINVAL;
2782
2783 } while (*p != 0);
2784
2785 *usec = r;
2786
2787 return 0;
2788}
2789
d88a251b
LP
2790int parse_nsec(const char *t, nsec_t *nsec) {
2791 static const struct {
2792 const char *suffix;
2793 nsec_t nsec;
2794 } table[] = {
2795 { "sec", NSEC_PER_SEC },
2796 { "s", NSEC_PER_SEC },
2797 { "min", NSEC_PER_MINUTE },
2798 { "hr", NSEC_PER_HOUR },
2799 { "h", NSEC_PER_HOUR },
2800 { "d", NSEC_PER_DAY },
2801 { "w", NSEC_PER_WEEK },
2802 { "msec", NSEC_PER_MSEC },
2803 { "ms", NSEC_PER_MSEC },
2804 { "m", NSEC_PER_MINUTE },
2805 { "usec", NSEC_PER_USEC },
2806 { "us", NSEC_PER_USEC },
2807 { "nsec", 1ULL },
2808 { "ns", 1ULL },
2809 { "", 1ULL }, /* default is nsec */
2810 };
2811
2812 const char *p;
2813 nsec_t r = 0;
2814
2815 assert(t);
2816 assert(nsec);
2817
2818 p = t;
2819 do {
2820 long long l;
2821 char *e;
2822 unsigned i;
2823
2824 errno = 0;
2825 l = strtoll(p, &e, 10);
2826
2827 if (errno != 0)
2828 return -errno;
2829
2830 if (l < 0)
2831 return -ERANGE;
2832
2833 if (e == p)
2834 return -EINVAL;
2835
2836 e += strspn(e, WHITESPACE);
2837
2838 for (i = 0; i < ELEMENTSOF(table); i++)
2839 if (startswith(e, table[i].suffix)) {
2840 r += (nsec_t) l * table[i].nsec;
2841 p = e + strlen(table[i].suffix);
2842 break;
2843 }
2844
2845 if (i >= ELEMENTSOF(table))
2846 return -EINVAL;
2847
2848 } while (*p != 0);
2849
2850 *nsec = r;
2851
2852 return 0;
2853}
2854
ab1f0633
LP
2855int parse_bytes(const char *t, off_t *bytes) {
2856 static const struct {
2857 const char *suffix;
2858 off_t factor;
2859 } table[] = {
2860 { "B", 1 },
2861 { "K", 1024ULL },
2862 { "M", 1024ULL*1024ULL },
2863 { "G", 1024ULL*1024ULL*1024ULL },
2864 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
32895bb3
LP
2865 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2866 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
ab1f0633
LP
2867 { "", 1 },
2868 };
2869
2870 const char *p;
2871 off_t r = 0;
2872
2873 assert(t);
2874 assert(bytes);
2875
2876 p = t;
2877 do {
2878 long long l;
2879 char *e;
2880 unsigned i;
2881
2882 errno = 0;
2883 l = strtoll(p, &e, 10);
2884
2885 if (errno != 0)
2886 return -errno;
2887
2888 if (l < 0)
2889 return -ERANGE;
2890
2891 if (e == p)
2892 return -EINVAL;
2893
2894 e += strspn(e, WHITESPACE);
2895
2896 for (i = 0; i < ELEMENTSOF(table); i++)
2897 if (startswith(e, table[i].suffix)) {
2898 r += (off_t) l * table[i].factor;
2899 p = e + strlen(table[i].suffix);
2900 break;
2901 }
2902
2903 if (i >= ELEMENTSOF(table))
2904 return -EINVAL;
2905
2906 } while (*p != 0);
2907
2908 *bytes = r;
2909
2910 return 0;
2911}
2912
843d2643
LP
2913int make_stdio(int fd) {
2914 int r, s, t;
2915
2916 assert(fd >= 0);
2917
73836c5c
LP
2918 r = dup3(fd, STDIN_FILENO, 0);
2919 s = dup3(fd, STDOUT_FILENO, 0);
2920 t = dup3(fd, STDERR_FILENO, 0);
843d2643
LP
2921
2922 if (fd >= 3)
2923 close_nointr_nofail(fd);
2924
2925 if (r < 0 || s < 0 || t < 0)
2926 return -errno;
2927
73836c5c 2928 /* We rely here that the new fd has O_CLOEXEC not set */
7862f62d 2929
843d2643
LP
2930 return 0;
2931}
2932
ade509ce
LP
2933int make_null_stdio(void) {
2934 int null_fd;
2935
cd3bd60a
LP
2936 null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
2937 if (null_fd < 0)
ade509ce
LP
2938 return -errno;
2939
2940 return make_stdio(null_fd);
2941}
2942
8407a5d0
LP
2943bool is_device_path(const char *path) {
2944
2945 /* Returns true on paths that refer to a device, either in
2946 * sysfs or in /dev */
2947
2948 return
2949 path_startswith(path, "/dev/") ||
2950 path_startswith(path, "/sys/");
2951}
2952
01f78473 2953int dir_is_empty(const char *path) {
a05f97b3 2954 _cleanup_closedir_ DIR *d;
01f78473 2955 int r;
01f78473 2956
a05f97b3
LP
2957 d = opendir(path);
2958 if (!d)
01f78473
LP
2959 return -errno;
2960
2961 for (;;) {
7d5e9c0f
LP
2962 struct dirent *de;
2963 union dirent_storage buf;
01f78473 2964
7d5e9c0f 2965 r = readdir_r(d, &buf.de, &de);
a05f97b3
LP
2966 if (r > 0)
2967 return -r;
01f78473 2968
a05f97b3
LP
2969 if (!de)
2970 return 1;
01f78473 2971
a05f97b3
LP
2972 if (!ignore_file(de->d_name))
2973 return 0;
2974 }
01f78473
LP
2975}
2976
d3782d60 2977unsigned long long random_ull(void) {
a05f97b3 2978 _cleanup_close_ int fd;
d3782d60
LP
2979 uint64_t ull;
2980 ssize_t r;
2981
ac0930c8
LP
2982 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
2983 if (fd < 0)
d3782d60
LP
2984 goto fallback;
2985
eb22ac37 2986 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
2987 if (r != sizeof(ull))
2988 goto fallback;
2989
2990 return ull;
2991
2992fallback:
2993 return random() * RAND_MAX + random();
2994}
2995
5b6319dc
LP
2996void rename_process(const char name[8]) {
2997 assert(name);
2998
5d6b1584
LP
2999 /* This is a like a poor man's setproctitle(). It changes the
3000 * comm field, argv[0], and also the glibc's internally used
3001 * name of the process. For the first one a limit of 16 chars
3002 * applies, to the second one usually one of 10 (i.e. length
3003 * of "/sbin/init"), to the third one one of 7 (i.e. length of
3004 * "systemd"). If you pass a longer string it will be
3005 * truncated */
5b6319dc 3006
5d6b1584 3007 prctl(PR_SET_NAME, name);
5b6319dc
LP
3008
3009 if (program_invocation_name)
3010 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
3011
3012 if (saved_argc > 0) {
3013 int i;
3014
3015 if (saved_argv[0])
3016 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
3017
3018 for (i = 1; i < saved_argc; i++) {
3019 if (!saved_argv[i])
3020 break;
3021
3022 memset(saved_argv[i], 0, strlen(saved_argv[i]));
3023 }
3024 }
5b6319dc
LP
3025}
3026
7d793605
LP
3027void sigset_add_many(sigset_t *ss, ...) {
3028 va_list ap;
3029 int sig;
3030
3031 assert(ss);
3032
3033 va_start(ap, ss);
3034 while ((sig = va_arg(ap, int)) > 0)
3035 assert_se(sigaddset(ss, sig) == 0);
3036 va_end(ap);
3037}
3038
ef2f1067
LP
3039char* gethostname_malloc(void) {
3040 struct utsname u;
3041
3042 assert_se(uname(&u) >= 0);
3043
344de609 3044 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
3045 return strdup(u.nodename);
3046
3047 return strdup(u.sysname);
3048}
3049
344de609
LP
3050bool hostname_is_set(void) {
3051 struct utsname u;
3052
3053 assert_se(uname(&u) >= 0);
3054
3055 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
3056}
3057
7c5f152a 3058static char *lookup_uid(uid_t uid) {
ef2f1067 3059 long bufsize;
a05f97b3
LP
3060 char *name;
3061 _cleanup_free_ char *buf = NULL;
ef2f1067 3062 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
3063
3064 /* Shortcut things to avoid NSS lookups */
3065 if (uid == 0)
3066 return strdup("root");
3067
7c5f152a
LP
3068 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
3069 if (bufsize <= 0)
ef2f1067
LP
3070 bufsize = 4096;
3071
7c5f152a
LP
3072 buf = malloc(bufsize);
3073 if (!buf)
ef2f1067
LP
3074 return NULL;
3075
a05f97b3
LP
3076 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
3077 return strdup(pw->pw_name);
ef2f1067
LP
3078
3079 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
3080 return NULL;
3081
3082 return name;
3083}
3084
7c5f152a
LP
3085char* getlogname_malloc(void) {
3086 uid_t uid;
3087 struct stat st;
3088
3089 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
3090 uid = st.st_uid;
3091 else
3092 uid = getuid();
3093
3094 return lookup_uid(uid);
3095}
3096
3097char *getusername_malloc(void) {
3098 const char *e;
3099
3100 e = getenv("USER");
3101 if (e)
3102 return strdup(e);
3103
3104 return lookup_uid(getuid());
3105}
3106
fc116c6a
LP
3107int getttyname_malloc(int fd, char **r) {
3108 char path[PATH_MAX], *c;
618e02c7 3109 int k;
8c6db833
LP
3110
3111 assert(r);
ef2f1067 3112
a05f97b3
LP
3113 k = ttyname_r(fd, path, sizeof(path));
3114 if (k != 0)
618e02c7 3115 return -k;
ef2f1067
LP
3116
3117 char_array_0(path);
3118
a05f97b3
LP
3119 c = strdup(startswith(path, "/dev/") ? path + 5 : path);
3120 if (!c)
8c6db833
LP
3121 return -ENOMEM;
3122
3123 *r = c;
3124 return 0;
3125}
3126
fc116c6a
LP
3127int getttyname_harder(int fd, char **r) {
3128 int k;
3129 char *s;
3130
a05f97b3
LP
3131 k = getttyname_malloc(fd, &s);
3132 if (k < 0)
fc116c6a
LP
3133 return k;
3134
3135 if (streq(s, "tty")) {
3136 free(s);
4d6d6518 3137 return get_ctty(0, NULL, r);
fc116c6a
LP
3138 }
3139
3140 *r = s;
3141 return 0;
3142}
3143
4d6d6518 3144int get_ctty_devnr(pid_t pid, dev_t *d) {
fc116c6a 3145 int k;
4d6d6518 3146 char line[LINE_MAX], *p, *fn;
fc116c6a
LP
3147 unsigned long ttynr;
3148 FILE *f;
3149
4d6d6518
LP
3150 if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
3151 return -ENOMEM;
3152
3153 f = fopen(fn, "re");
3154 free(fn);
3155 if (!f)
fc116c6a
LP
3156 return -errno;
3157
4d6d6518 3158 if (!fgets(line, sizeof(line), f)) {
35d50f55 3159 k = feof(f) ? -EIO : -errno;
fc116c6a
LP
3160 fclose(f);
3161 return k;
3162 }
3163
3164 fclose(f);
3165
4d6d6518
LP
3166 p = strrchr(line, ')');
3167 if (!p)
fc116c6a
LP
3168 return -EIO;
3169
3170 p++;
3171
3172 if (sscanf(p, " "
3173 "%*c " /* state */
3174 "%*d " /* ppid */
3175 "%*d " /* pgrp */
3176 "%*d " /* session */
3177 "%lu ", /* ttynr */
3178 &ttynr) != 1)
3179 return -EIO;
3180
3181 *d = (dev_t) ttynr;
3182 return 0;
3183}
3184
4d6d6518 3185int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 3186 int k;
20c03b7b 3187 char fn[PATH_MAX], *s, *b, *p;
fc116c6a
LP
3188 dev_t devnr;
3189
3190 assert(r);
3191
4d6d6518
LP
3192 k = get_ctty_devnr(pid, &devnr);
3193 if (k < 0)
fc116c6a
LP
3194 return k;
3195
3196 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
3197 char_array_0(fn);
3198
3199 if ((k = readlink_malloc(fn, &s)) < 0) {
3200
3201 if (k != -ENOENT)
3202 return k;
3203
46824d0e
LP
3204 /* This is an ugly hack */
3205 if (major(devnr) == 136) {
3206 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
3207 return -ENOMEM;
3208
3209 *r = b;
3210 if (_devnr)
3211 *_devnr = devnr;
3212
3213 return 0;
3214 }
3215
fc116c6a
LP
3216 /* Probably something like the ptys which have no
3217 * symlink in /dev/char. Let's return something
3218 * vaguely useful. */
3219
3220 if (!(b = strdup(fn + 5)))
3221 return -ENOMEM;
3222
3223 *r = b;
46824d0e
LP
3224 if (_devnr)
3225 *_devnr = devnr;
3226
fc116c6a
LP
3227 return 0;
3228 }
3229
3230 if (startswith(s, "/dev/"))
3231 p = s + 5;
3232 else if (startswith(s, "../"))
3233 p = s + 3;
3234 else
3235 p = s;
3236
3237 b = strdup(p);
3238 free(s);
3239
3240 if (!b)
3241 return -ENOMEM;
3242
3243 *r = b;
46824d0e
LP
3244 if (_devnr)
3245 *_devnr = devnr;
3246
fc116c6a
LP
3247 return 0;
3248}
3249
f56d5db9 3250int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
3251 DIR *d;
3252 int ret = 0;
3253
3254 assert(fd >= 0);
3255
3256 /* This returns the first error we run into, but nevertheless
7925c22a 3257 * tries to go on. This closes the passed fd. */
8c6db833 3258
d4d046e3
LP
3259 d = fdopendir(fd);
3260 if (!d) {
8c6db833 3261 close_nointr_nofail(fd);
4c633005
LP
3262
3263 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
3264 }
3265
3266 for (;;) {
7d5e9c0f
LP
3267 struct dirent *de;
3268 union dirent_storage buf;
7925c22a
LP
3269 bool is_dir, keep_around;
3270 struct stat st;
8c6db833
LP
3271 int r;
3272
7d5e9c0f 3273 r = readdir_r(d, &buf.de, &de);
d4d046e3
LP
3274 if (r != 0 && ret == 0) {
3275 ret = -r;
8c6db833
LP
3276 break;
3277 }
3278
3279 if (!de)
3280 break;
3281
3282 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
3283 continue;
3284
7925c22a
LP
3285 if (de->d_type == DT_UNKNOWN ||
3286 honour_sticky ||
3287 (de->d_type == DT_DIR && root_dev)) {
8c6db833 3288 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 3289 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3290 ret = -errno;
3291 continue;
3292 }
3293
3294 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
3295 keep_around =
3296 honour_sticky &&
3297 (st.st_uid == 0 || st.st_uid == getuid()) &&
3298 (st.st_mode & S_ISVTX);
ad293f5a 3299 } else {
8c6db833 3300 is_dir = de->d_type == DT_DIR;
7925c22a 3301 keep_around = false;
ad293f5a 3302 }
8c6db833
LP
3303
3304 if (is_dir) {
3305 int subdir_fd;
8c6db833 3306
597f43c7 3307 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
3308 if (root_dev && st.st_dev != root_dev->st_dev)
3309 continue;
8c6db833 3310
7925c22a
LP
3311 subdir_fd = openat(fd, de->d_name,
3312 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3313 if (subdir_fd < 0) {
3314 if (ret == 0 && errno != ENOENT)
3315 ret = -errno;
3316 continue;
3317 }
3318
b3d28469 3319 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
3320 if (r < 0 && ret == 0)
3321 ret = r;
3322
3323 if (!keep_around)
3324 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
3325 if (ret == 0 && errno != ENOENT)
3326 ret = -errno;
3327 }
3328
3329 } else if (!only_dirs && !keep_around) {
8c6db833
LP
3330
3331 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 3332 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3333 ret = -errno;
3334 }
3335 }
3336 }
3337
3338 closedir(d);
3339
3340 return ret;
3341}
3342
f56d5db9
LP
3343int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
3344 struct statfs s;
3345
3346 assert(fd >= 0);
3347
3348 if (fstatfs(fd, &s) < 0) {
3349 close_nointr_nofail(fd);
3350 return -errno;
3351 }
3352
3353 /* We refuse to clean disk file systems with this call. This
3354 * is extra paranoia just to be sure we never ever remove
3355 * non-state data */
3356
3357 if (s.f_type != TMPFS_MAGIC &&
3358 s.f_type != RAMFS_MAGIC) {
3359 log_error("Attempted to remove disk file system, and we can't allow that.");
3360 close_nointr_nofail(fd);
3361 return -EPERM;
3362 }
3363
3364 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
3365}
3366
3367static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
3368 int fd, r;
3369 struct statfs s;
8c6db833
LP
3370
3371 assert(path);
3372
f56d5db9
LP
3373 /* We refuse to clean the root file system with this
3374 * call. This is extra paranoia to never cause a really
3375 * seriously broken system. */
3376 if (path_equal(path, "/")) {
3377 log_error("Attempted to remove entire root file system, and we can't allow that.");
3378 return -EPERM;
3379 }
461b1822 3380
d4d046e3
LP
3381 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3382 if (fd < 0) {
8c6db833
LP
3383
3384 if (errno != ENOTDIR)
3385 return -errno;
3386
f56d5db9
LP
3387 if (!dangerous) {
3388 if (statfs(path, &s) < 0)
3389 return -errno;
3390
3391 if (s.f_type != TMPFS_MAGIC &&
3392 s.f_type != RAMFS_MAGIC) {
3393 log_error("Attempted to remove disk file system, and we can't allow that.");
3394 return -EPERM;
3395 }
3396 }
3397
8c6db833 3398 if (delete_root && !only_dirs)
d4d046e3 3399 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
3400 return -errno;
3401
3402 return 0;
3403 }
3404
f56d5db9
LP
3405 if (!dangerous) {
3406 if (fstatfs(fd, &s) < 0) {
3407 close_nointr_nofail(fd);
3408 return -errno;
3409 }
ad293f5a 3410
f56d5db9
LP
3411 if (s.f_type != TMPFS_MAGIC &&
3412 s.f_type != RAMFS_MAGIC) {
3413 log_error("Attempted to remove disk file system, and we can't allow that.");
3414 close_nointr_nofail(fd);
3415 return -EPERM;
3416 }
3417 }
3418
3419 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
3420 if (delete_root) {
3421
8d53b453 3422 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 3423 return r;
8c6db833 3424
e27796a0 3425 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
3426 if (r == 0)
3427 r = -errno;
3428 }
ad293f5a 3429 }
8c6db833
LP
3430
3431 return r;
3432}
3433
f56d5db9
LP
3434int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3435 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
3436}
3437
3438int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3439 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
3440}
3441
8c6db833
LP
3442int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
3443 assert(path);
3444
3445 /* Under the assumption that we are running privileged we
3446 * first change the access mode and only then hand out
3447 * ownership to avoid a window where access is too open. */
3448
8d53b453
LP
3449 if (mode != (mode_t) -1)
3450 if (chmod(path, mode) < 0)
3451 return -errno;
8c6db833 3452
8d53b453
LP
3453 if (uid != (uid_t) -1 || gid != (gid_t) -1)
3454 if (chown(path, uid, gid) < 0)
3455 return -errno;
8c6db833
LP
3456
3457 return 0;
ef2f1067
LP
3458}
3459
f4b47811
LP
3460int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
3461 assert(fd >= 0);
3462
3463 /* Under the assumption that we are running privileged we
3464 * first change the access mode and only then hand out
3465 * ownership to avoid a window where access is too open. */
3466
3467 if (fchmod(fd, mode) < 0)
3468 return -errno;
3469
3470 if (fchown(fd, uid, gid) < 0)
3471 return -errno;
3472
3473 return 0;
3474}
3475
82c121a4
LP
3476cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
3477 cpu_set_t *r;
3478 unsigned n = 1024;
3479
3480 /* Allocates the cpuset in the right size */
3481
3482 for (;;) {
3483 if (!(r = CPU_ALLOC(n)))
3484 return NULL;
3485
3486 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
3487 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
3488
3489 if (ncpus)
3490 *ncpus = n;
3491
3492 return r;
3493 }
3494
3495 CPU_FREE(r);
3496
3497 if (errno != EINVAL)
3498 return NULL;
3499
3500 n *= 2;
3501 }
3502}
3503
669bec5d 3504int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
9ab7a8d2 3505 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
3506 _cleanup_free_ char *s = NULL;
3507 _cleanup_close_ int fd = -1;
81beb750
LP
3508 struct iovec iovec[5];
3509 int n = 0;
9e58ff9c
LP
3510
3511 assert(format);
3512
9ab7a8d2 3513 /* This is independent of logging, as status messages are
9e58ff9c
LP
3514 * optional and go exclusively to the console. */
3515
3516 if (vasprintf(&s, format, ap) < 0)
669bec5d 3517 return log_oom();
9e58ff9c 3518
67e5cc4f 3519 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 3520 if (fd < 0)
669bec5d 3521 return fd;
9e58ff9c 3522
67e5cc4f 3523 if (ellipse) {
9ab7a8d2
MS
3524 char *e;
3525 size_t emax, sl;
3526 int c;
3527
67e5cc4f
LP
3528 c = fd_columns(fd);
3529 if (c <= 0)
3530 c = 80;
81beb750 3531
669bec5d 3532 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
3533
3534 emax = c - sl - 1;
3535 if (emax < 3)
3536 emax = 3;
81beb750 3537
67e5cc4f
LP
3538 e = ellipsize(s, emax, 75);
3539 if (e) {
3540 free(s);
3541 s = e;
3542 }
81beb750
LP
3543 }
3544
3545 zero(iovec);
81beb750 3546
9ab7a8d2
MS
3547 if (status) {
3548 if (!isempty(status)) {
3549 IOVEC_SET_STRING(iovec[n++], "[");
3550 IOVEC_SET_STRING(iovec[n++], status);
3551 IOVEC_SET_STRING(iovec[n++], "] ");
3552 } else
3553 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
3554 }
3555
9ab7a8d2
MS
3556 IOVEC_SET_STRING(iovec[n++], s);
3557 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 3558
669bec5d
LP
3559 if (writev(fd, iovec, n) < 0)
3560 return -errno;
9e58ff9c 3561
669bec5d 3562 return 0;
9e58ff9c
LP
3563}
3564
669bec5d 3565int status_printf(const char *status, bool ellipse, const char *format, ...) {
c846ff47 3566 va_list ap;
669bec5d 3567 int r;
c846ff47
LP
3568
3569 assert(format);
3570
3571 va_start(ap, format);
669bec5d 3572 r = status_vprintf(status, ellipse, format, ap);
c846ff47 3573 va_end(ap);
669bec5d
LP
3574
3575 return r;
c846ff47
LP
3576}
3577
669bec5d 3578int status_welcome(void) {
10aa7034 3579 int r;
669bec5d
LP
3580 _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
3581
3582 r = parse_env_file("/etc/os-release", NEWLINE,
3583 "PRETTY_NAME", &pretty_name,
3584 "ANSI_COLOR", &ansi_color,
3585 NULL);
3586 if (r < 0 && r != -ENOENT)
3587 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3588
3589 return status_printf(NULL, false,
3590 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3591 isempty(ansi_color) ? "1" : ansi_color,
3592 isempty(pretty_name) ? "Linux" : pretty_name);
c846ff47
LP
3593}
3594
fab56fc5
LP
3595char *replace_env(const char *format, char **env) {
3596 enum {
3597 WORD,
c24eb49e 3598 CURLY,
fab56fc5
LP
3599 VARIABLE
3600 } state = WORD;
3601
3602 const char *e, *word = format;
3603 char *r = NULL, *k;
3604
3605 assert(format);
3606
3607 for (e = format; *e; e ++) {
3608
3609 switch (state) {
3610
3611 case WORD:
3612 if (*e == '$')
c24eb49e 3613 state = CURLY;
fab56fc5
LP
3614 break;
3615
c24eb49e
LP
3616 case CURLY:
3617 if (*e == '{') {
fab56fc5
LP
3618 if (!(k = strnappend(r, word, e-word-1)))
3619 goto fail;
3620
3621 free(r);
3622 r = k;
3623
3624 word = e-1;
3625 state = VARIABLE;
3626
3627 } else if (*e == '$') {
3628 if (!(k = strnappend(r, word, e-word)))
3629 goto fail;
3630
3631 free(r);
3632 r = k;
3633
3634 word = e+1;
3635 state = WORD;
3636 } else
3637 state = WORD;
3638 break;
3639
3640 case VARIABLE:
c24eb49e 3641 if (*e == '}') {
b95cf362 3642 const char *t;
fab56fc5 3643
b95cf362
LP
3644 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
3645 t = "";
fab56fc5 3646
b95cf362
LP
3647 if (!(k = strappend(r, t)))
3648 goto fail;
fab56fc5 3649
b95cf362
LP
3650 free(r);
3651 r = k;
fab56fc5 3652
b95cf362 3653 word = e+1;
fab56fc5
LP
3654 state = WORD;
3655 }
3656 break;
3657 }
3658 }
3659
3660 if (!(k = strnappend(r, word, e-word)))
3661 goto fail;
3662
3663 free(r);
3664 return k;
3665
3666fail:
3667 free(r);
3668 return NULL;
3669}
3670
3671char **replace_env_argv(char **argv, char **env) {
3672 char **r, **i;
c24eb49e
LP
3673 unsigned k = 0, l = 0;
3674
3675 l = strv_length(argv);
fab56fc5 3676
c24eb49e 3677 if (!(r = new(char*, l+1)))
fab56fc5
LP
3678 return NULL;
3679
3680 STRV_FOREACH(i, argv) {
c24eb49e
LP
3681
3682 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3683 if ((*i)[0] == '$' && (*i)[1] != '{') {
3684 char *e;
3685 char **w, **m;
3686 unsigned q;
c24eb49e 3687
b95cf362 3688 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
3689
3690 if (!(m = strv_split_quoted(e))) {
3691 r[k] = NULL;
3692 strv_free(r);
3693 return NULL;
3694 }
b95cf362
LP
3695 } else
3696 m = NULL;
c24eb49e 3697
b95cf362
LP
3698 q = strv_length(m);
3699 l = l + q - 1;
c24eb49e 3700
b95cf362
LP
3701 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3702 r[k] = NULL;
3703 strv_free(r);
3704 strv_free(m);
3705 return NULL;
3706 }
c24eb49e 3707
b95cf362
LP
3708 r = w;
3709 if (m) {
c24eb49e
LP
3710 memcpy(r + k, m, q * sizeof(char*));
3711 free(m);
c24eb49e 3712 }
b95cf362
LP
3713
3714 k += q;
3715 continue;
c24eb49e
LP
3716 }
3717
3718 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3719 if (!(r[k++] = replace_env(*i, env))) {
3720 strv_free(r);
3721 return NULL;
3722 }
3723 }
3724
3725 r[k] = NULL;
3726 return r;
3727}
3728
81beb750
LP
3729int fd_columns(int fd) {
3730 struct winsize ws;
3731 zero(ws);
3732
3733 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3734 return -errno;
3735
3736 if (ws.ws_col <= 0)
3737 return -EIO;
3738
3739 return ws.ws_col;
3740}
3741
11f96fac
ZJS
3742static unsigned columns_cached(bool cached) {
3743 static __thread int parsed_columns = 0, env_columns = -1;
fa776d8e
LP
3744 const char *e;
3745
11f96fac 3746 if (_likely_(parsed_columns > 0 && cached))
fa776d8e
LP
3747 return parsed_columns;
3748
11f96fac
ZJS
3749 if (_unlikely_(env_columns == -1)) {
3750 e = getenv("COLUMNS");
3751 if (e)
3752 env_columns = atoi(e);
3753 else
3754 env_columns = 0;
3755 }
fa776d8e 3756
11f96fac
ZJS
3757 if (env_columns > 0) {
3758 parsed_columns = env_columns;
3759 return parsed_columns;
3760 }
3761
3762 if (parsed_columns <= 0 || !cached)
81beb750 3763 parsed_columns = fd_columns(STDOUT_FILENO);
fa776d8e
LP
3764
3765 if (parsed_columns <= 0)
3766 parsed_columns = 80;
3767
3768 return parsed_columns;
3769}
3770
11f96fac
ZJS
3771unsigned columns(void) {
3772 return columns_cached(true);
3773}
3774
3775unsigned columns_uncached(void) {
3776 return columns_cached(false);
3777}
3778
8f2d43a0
LP
3779int fd_lines(int fd) {
3780 struct winsize ws;
3781 zero(ws);
3782
3783 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3784 return -errno;
3785
3786 if (ws.ws_row <= 0)
3787 return -EIO;
3788
3789 return ws.ws_row;
3790}
3791
3792unsigned lines(void) {
3793 static __thread int parsed_lines = 0;
3794 const char *e;
3795
3796 if (_likely_(parsed_lines > 0))
3797 return parsed_lines;
3798
3799 e = getenv("LINES");
3800 if (e)
3801 parsed_lines = atoi(e);
3802
3803 if (parsed_lines <= 0)
3804 parsed_lines = fd_lines(STDOUT_FILENO);
3805
3806 if (parsed_lines <= 0)
3807 parsed_lines = 25;
3808
3809 return parsed_lines;
3810}
3811
b4f10a5e
LP
3812int running_in_chroot(void) {
3813 struct stat a, b;
3814
3815 zero(a);
3816 zero(b);
3817
3818 /* Only works as root */
3819
3820 if (stat("/proc/1/root", &a) < 0)
3821 return -errno;
3822
3823 if (stat("/", &b) < 0)
3824 return -errno;
3825
3826 return
3827 a.st_dev != b.st_dev ||
3828 a.st_ino != b.st_ino;
3829}
3830
72f59706
LP
3831char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3832 size_t x;
8fe914ec
LP
3833 char *r;
3834
3835 assert(s);
3836 assert(percent <= 100);
72f59706 3837 assert(new_length >= 3);
8fe914ec 3838
72f59706
LP
3839 if (old_length <= 3 || old_length <= new_length)
3840 return strndup(s, old_length);
8fe914ec 3841
72f59706
LP
3842 r = new0(char, new_length+1);
3843 if (!r)
8fe914ec
LP
3844 return r;
3845
72f59706 3846 x = (new_length * percent) / 100;
8fe914ec 3847
72f59706
LP
3848 if (x > new_length - 3)
3849 x = new_length - 3;
8fe914ec
LP
3850
3851 memcpy(r, s, x);
3852 r[x] = '.';
3853 r[x+1] = '.';
3854 r[x+2] = '.';
3855 memcpy(r + x + 3,
72f59706
LP
3856 s + old_length - (new_length - x - 3),
3857 new_length - x - 3);
8fe914ec
LP
3858
3859 return r;
3860}
3861
72f59706
LP
3862char *ellipsize(const char *s, size_t length, unsigned percent) {
3863 return ellipsize_mem(s, strlen(s), length, percent);
3864}
3865
f6144808
LP
3866int touch(const char *path) {
3867 int fd;
3868
3869 assert(path);
3870
73836c5c
LP
3871 /* This just opens the file for writing, ensuring it
3872 * exists. It doesn't call utimensat() the way /usr/bin/touch
3873 * does it. */
3874
3875 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3876 if (fd < 0)
f6144808
LP
3877 return -errno;
3878
3879 close_nointr_nofail(fd);
3880 return 0;
3881}
afea26ad 3882
97c4a07d 3883char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3884 size_t l;
3885 assert(s);
3886
73836c5c
LP
3887 /* This is rather stupid, simply removes the heading and
3888 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3889 * escaping or anything. We should make this smarter one
3890 * day...*/
73836c5c 3891
31ed59c5
LP
3892 l = strlen(s);
3893 if (l < 2)
11ce3427
LP
3894 return strdup(s);
3895
97c4a07d 3896 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3897 return strndup(s+1, l-2);
3898
3899 return strdup(s);
3900}
3901
5f7c426e 3902char *normalize_env_assignment(const char *s) {
57f30678
LP
3903 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3904 char *eq, *r;
5f7c426e 3905
57f30678
LP
3906 eq = strchr(s, '=');
3907 if (!eq) {
3908 char *t;
5f7c426e 3909
57f30678
LP
3910 r = strdup(s);
3911 if (!r)
5f7c426e
LP
3912 return NULL;
3913
57f30678
LP
3914 t = strstrip(r);
3915 if (t == r)
3916 return r;
3917
3918 memmove(r, t, strlen(t) + 1);
3919 return r;
5f7c426e
LP
3920 }
3921
57f30678
LP
3922 name = strndup(s, eq - s);
3923 if (!name)
5f7c426e
LP
3924 return NULL;
3925
57f30678
LP
3926 p = strdup(eq + 1);
3927 if (!p)
5f7c426e 3928 return NULL;
5f7c426e
LP
3929
3930 value = unquote(strstrip(p), QUOTES);
57f30678 3931 if (!value)
5f7c426e 3932 return NULL;
5f7c426e 3933
57f30678 3934 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3935 r = NULL;
3936
5f7c426e
LP
3937 return r;
3938}
3939
8e12a6ae 3940int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3941 siginfo_t dummy;
3942
2e78aa99 3943 assert(pid >= 1);
1968a360
LP
3944
3945 if (!status)
3946 status = &dummy;
2e78aa99
LP
3947
3948 for (;;) {
8e12a6ae
LP
3949 zero(*status);
3950
3951 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3952
3953 if (errno == EINTR)
3954 continue;
3955
3956 return -errno;
3957 }
3958
3959 return 0;
3960 }
3961}
3962
97c4a07d
LP
3963int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3964 int r;
3965 siginfo_t status;
3966
3967 assert(name);
3968 assert(pid > 1);
3969
d87be9b0
LP
3970 r = wait_for_terminate(pid, &status);
3971 if (r < 0) {
97c4a07d
LP
3972 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3973 return r;
3974 }
3975
3976 if (status.si_code == CLD_EXITED) {
3977 if (status.si_status != 0) {
3978 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3979 return status.si_status;
97c4a07d
LP
3980 }
3981
3982 log_debug("%s succeeded.", name);
3983 return 0;
3984
3985 } else if (status.si_code == CLD_KILLED ||
3986 status.si_code == CLD_DUMPED) {
3987
3988 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3989 return -EPROTO;
3990 }
3991
3992 log_warning("%s failed due to unknown reason.", name);
3993 return -EPROTO;
97c4a07d
LP
3994}
3995
6a39419f 3996_noreturn_ void freeze(void) {
720ce21d
LP
3997
3998 /* Make sure nobody waits for us on a socket anymore */
3999 close_all_fds(NULL, 0);
4000
c29597a1
LP
4001 sync();
4002
3c14d26c
LP
4003 for (;;)
4004 pause();
4005}
4006
00dc5d76
LP
4007bool null_or_empty(struct stat *st) {
4008 assert(st);
4009
4010 if (S_ISREG(st->st_mode) && st->st_size <= 0)
4011 return true;
4012
c8f26f42 4013 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
4014 return true;
4015
4016 return false;
4017}
4018
83096483
LP
4019int null_or_empty_path(const char *fn) {
4020 struct stat st;
4021
4022 assert(fn);
4023
4024 if (stat(fn, &st) < 0)
4025 return -errno;
4026
4027 return null_or_empty(&st);
4028}
4029
a247755d 4030DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
4031 int nfd;
4032 DIR *d;
4033
73836c5c
LP
4034 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
4035 if (nfd < 0)
c4731d11
LP
4036 return NULL;
4037
73836c5c
LP
4038 d = fdopendir(nfd);
4039 if (!d) {
c4731d11
LP
4040 close_nointr_nofail(nfd);
4041 return NULL;
4042 }
4043
4044 return d;
3b63d2d3
LP
4045}
4046
8a0867d6
LP
4047int signal_from_string_try_harder(const char *s) {
4048 int signo;
4049 assert(s);
4050
73836c5c
LP
4051 signo = signal_from_string(s);
4052 if (signo <= 0)
8a0867d6
LP
4053 if (startswith(s, "SIG"))
4054 return signal_from_string(s+3);
4055
4056 return signo;
4057}
4058
10717a1a
LP
4059void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
4060
4061 assert(f);
4062 assert(name);
4063 assert(t);
4064
4065 if (!dual_timestamp_is_set(t))
4066 return;
4067
4068 fprintf(f, "%s=%llu %llu\n",
4069 name,
4070 (unsigned long long) t->realtime,
4071 (unsigned long long) t->monotonic);
4072}
4073
799fd0fd 4074void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
10717a1a
LP
4075 unsigned long long a, b;
4076
10717a1a
LP
4077 assert(value);
4078 assert(t);
4079
4080 if (sscanf(value, "%lli %llu", &a, &b) != 2)
4081 log_debug("Failed to parse finish timestamp value %s", value);
4082 else {
4083 t->realtime = a;
4084 t->monotonic = b;
4085 }
4086}
4087
383182b5 4088static char *tag_to_udev_node(const char *tagvalue, const char *by) {
e23a0ce8
LP
4089 char *dn, *t, *u;
4090 int r;
4091
4092 /* FIXME: to follow udev's logic 100% we need to leave valid
4093 * UTF8 chars unescaped */
4094
383182b5
DR
4095 u = unquote(tagvalue, "\"\'");
4096 if (u == NULL)
4097 return NULL;
e23a0ce8 4098
383182b5
DR
4099 t = xescape(u, "/ ");
4100 free(u);
e23a0ce8 4101
383182b5
DR
4102 if (t == NULL)
4103 return NULL;
e23a0ce8 4104
383182b5
DR
4105 r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
4106 free(t);
e23a0ce8 4107
383182b5
DR
4108 if (r < 0)
4109 return NULL;
e23a0ce8 4110
383182b5
DR
4111 return dn;
4112}
e23a0ce8 4113
383182b5 4114char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
4115 assert(p);
4116
383182b5
DR
4117 if (startswith(p, "LABEL="))
4118 return tag_to_udev_node(p+6, "label");
e23a0ce8 4119
383182b5
DR
4120 if (startswith(p, "UUID="))
4121 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 4122
84cc2abf
DR
4123 if (startswith(p, "PARTUUID="))
4124 return tag_to_udev_node(p+9, "partuuid");
4125
4126 if (startswith(p, "PARTLABEL="))
4127 return tag_to_udev_node(p+10, "partlabel");
4128
e23a0ce8
LP
4129 return strdup(p);
4130}
4131
f212ac12
LP
4132bool tty_is_vc(const char *tty) {
4133 assert(tty);
4134
4135 if (startswith(tty, "/dev/"))
4136 tty += 5;
4137
98a28fef
LP
4138 return vtnr_from_tty(tty) >= 0;
4139}
4140
d1122ad5
LP
4141bool tty_is_console(const char *tty) {
4142 assert(tty);
4143
4144 if (startswith(tty, "/dev/"))
4145 tty += 5;
4146
4147 return streq(tty, "console");
4148}
4149
98a28fef
LP
4150int vtnr_from_tty(const char *tty) {
4151 int i, r;
4152
4153 assert(tty);
4154
4155 if (startswith(tty, "/dev/"))
4156 tty += 5;
4157
4158 if (!startswith(tty, "tty") )
4159 return -EINVAL;
4160
4161 if (tty[3] < '0' || tty[3] > '9')
4162 return -EINVAL;
4163
4164 r = safe_atoi(tty+3, &i);
4165 if (r < 0)
4166 return r;
4167
4168 if (i < 0 || i > 63)
4169 return -EINVAL;
4170
4171 return i;
f212ac12
LP
4172}
4173
3043935f 4174bool tty_is_vc_resolve(const char *tty) {
3030ccd7 4175 char *active = NULL;
3043935f 4176 bool b;
3030ccd7 4177
e3aa71c3
LP
4178 assert(tty);
4179
4180 if (startswith(tty, "/dev/"))
4181 tty += 5;
4182
3d9a4122
LP
4183 /* Resolve where /dev/console is pointing to, if /sys is
4184 * actually ours (i.e. not read-only-mounted which is a sign
4185 * for container setups) */
4186 if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
3030ccd7 4187 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4188 /* If multiple log outputs are configured the
4189 * last one is what /dev/console points to */
3043935f
LP
4190 tty = strrchr(active, ' ');
4191 if (tty)
079a09fb
LP
4192 tty++;
4193 else
4194 tty = active;
3030ccd7
LP
4195 }
4196
3043935f 4197 b = tty_is_vc(tty);
3030ccd7 4198 free(active);
e3aa71c3 4199
3043935f
LP
4200 return b;
4201}
4202
4203const char *default_term_for_tty(const char *tty) {
4204 assert(tty);
4205
acda6a05 4206 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
4207}
4208
87d2c1ff 4209bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4210 assert(de);
4211
4212 if (ignore_file(de->d_name))
4213 return false;
4214
4215 if (de->d_type != DT_REG &&
4216 de->d_type != DT_LNK &&
4217 de->d_type != DT_UNKNOWN)
4218 return false;
4219
4220 return true;
4221}
4222
87d2c1ff
LP
4223bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4224 assert(de);
4225
a228a22f
LP
4226 if (de->d_type != DT_REG &&
4227 de->d_type != DT_LNK &&
4228 de->d_type != DT_UNKNOWN)
4229 return false;
4230
4231 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
4232 return false;
4233
4234 return endswith(de->d_name, suffix);
4235}
4236
83cc030f
LP
4237void execute_directory(const char *directory, DIR *d, char *argv[]) {
4238 DIR *_d = NULL;
4239 struct dirent *de;
4240 Hashmap *pids = NULL;
4241
4242 assert(directory);
4243
4244 /* Executes all binaries in a directory in parallel and waits
4245 * until all they all finished. */
4246
4247 if (!d) {
4248 if (!(_d = opendir(directory))) {
4249
4250 if (errno == ENOENT)
4251 return;
4252
4253 log_error("Failed to enumerate directory %s: %m", directory);
4254 return;
4255 }
4256
4257 d = _d;
4258 }
4259
4260 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4261 log_error("Failed to allocate set.");
4262 goto finish;
4263 }
4264
4265 while ((de = readdir(d))) {
4266 char *path;
4267 pid_t pid;
4268 int k;
4269
fb19a739 4270 if (!dirent_is_file(de))
83cc030f
LP
4271 continue;
4272
4273 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 4274 log_oom();
83cc030f
LP
4275 continue;
4276 }
4277
4278 if ((pid = fork()) < 0) {
4279 log_error("Failed to fork: %m");
4280 free(path);
4281 continue;
4282 }
4283
4284 if (pid == 0) {
4285 char *_argv[2];
4286 /* Child */
4287
4288 if (!argv) {
4289 _argv[0] = path;
4290 _argv[1] = NULL;
4291 argv = _argv;
4292 } else
6edd7d0a 4293 argv[0] = path;
83cc030f
LP
4294
4295 execv(path, argv);
4296
4297 log_error("Failed to execute %s: %m", path);
4298 _exit(EXIT_FAILURE);
4299 }
4300
4301 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4302
4303 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4304 log_error("Failed to add PID to set: %s", strerror(-k));
4305 free(path);
4306 }
4307 }
4308
4309 while (!hashmap_isempty(pids)) {
ec3f9b53 4310 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
4311 siginfo_t si;
4312 char *path;
4313
4314 zero(si);
ec3f9b53 4315 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
4316
4317 if (errno == EINTR)
4318 continue;
4319
4320 log_error("waitid() failed: %m");
4321 goto finish;
4322 }
4323
4324 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 4325 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
4326 if (si.si_code == CLD_EXITED)
4327 log_error("%s exited with exit status %i.", path, si.si_status);
4328 else
4329 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4330 } else
4331 log_debug("%s exited successfully.", path);
4332
4333 free(path);
4334 }
4335 }
4336
4337finish:
4338 if (_d)
4339 closedir(_d);
4340
4341 if (pids)
4342 hashmap_free_free(pids);
4343}
4344
430c18ed
LP
4345int kill_and_sigcont(pid_t pid, int sig) {
4346 int r;
4347
4348 r = kill(pid, sig) < 0 ? -errno : 0;
4349
4350 if (r >= 0)
4351 kill(pid, SIGCONT);
4352
4353 return r;
4354}
4355
05feefe0
LP
4356bool nulstr_contains(const char*nulstr, const char *needle) {
4357 const char *i;
4358
4359 if (!nulstr)
4360 return false;
4361
4362 NULSTR_FOREACH(i, nulstr)
4363 if (streq(i, needle))
4364 return true;
4365
4366 return false;
4367}
4368
6faa1114 4369bool plymouth_running(void) {
9408a2d2 4370 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4371}
4372
9beb3f4d
LP
4373char* strshorten(char *s, size_t l) {
4374 assert(s);
4375
4376 if (l < strlen(s))
4377 s[l] = 0;
4378
4379 return s;
4380}
4381
4382static bool hostname_valid_char(char c) {
4383 return
4384 (c >= 'a' && c <= 'z') ||
4385 (c >= 'A' && c <= 'Z') ||
4386 (c >= '0' && c <= '9') ||
4387 c == '-' ||
4388 c == '_' ||
4389 c == '.';
4390}
4391
4392bool hostname_is_valid(const char *s) {
4393 const char *p;
4394
4395 if (isempty(s))
4396 return false;
4397
4398 for (p = s; *p; p++)
4399 if (!hostname_valid_char(*p))
4400 return false;
4401
4402 if (p-s > HOST_NAME_MAX)
4403 return false;
4404
4405 return true;
4406}
4407
4408char* hostname_cleanup(char *s) {
4409 char *p, *d;
4410
4411 for (p = s, d = s; *p; p++)
4412 if ((*p >= 'a' && *p <= 'z') ||
4413 (*p >= 'A' && *p <= 'Z') ||
4414 (*p >= '0' && *p <= '9') ||
4415 *p == '-' ||
4416 *p == '_' ||
4417 *p == '.')
4418 *(d++) = *p;
4419
4420 *d = 0;
4421
4422 strshorten(s, HOST_NAME_MAX);
4423 return s;
4424}
4425
1325aa42
LP
4426int pipe_eof(int fd) {
4427 struct pollfd pollfd;
4428 int r;
4429
4430 zero(pollfd);
4431 pollfd.fd = fd;
4432 pollfd.events = POLLIN|POLLHUP;
4433
4434 r = poll(&pollfd, 1, 0);
4435 if (r < 0)
4436 return -errno;
4437
4438 if (r == 0)
4439 return 0;
4440
4441 return pollfd.revents & POLLHUP;
4442}
4443
8f2d43a0 4444int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
4445 struct pollfd pollfd;
4446 int r;
4447
4448 zero(pollfd);
4449 pollfd.fd = fd;
4450 pollfd.events = event;
4451
8f2d43a0 4452 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
4453 if (r < 0)
4454 return -errno;
4455
4456 if (r == 0)
4457 return 0;
4458
4459 return pollfd.revents;
4460}
4461
5a3ab509
LP
4462int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4463 FILE *f;
4464 char *t;
4465 const char *fn;
4466 size_t k;
4467 int fd;
4468
4469 assert(path);
4470 assert(_f);
4471 assert(_temp_path);
4472
4473 t = new(char, strlen(path) + 1 + 6 + 1);
4474 if (!t)
4475 return -ENOMEM;
4476
9eb977db 4477 fn = path_get_file_name(path);
5a3ab509
LP
4478 k = fn-path;
4479 memcpy(t, path, k);
4480 t[k] = '.';
4481 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4482
4483 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4484 if (fd < 0) {
4485 free(t);
4486 return -errno;
4487 }
4488
4489 f = fdopen(fd, "we");
4490 if (!f) {
4491 unlink(t);
4492 free(t);
4493 return -errno;
4494 }
4495
4496 *_f = f;
4497 *_temp_path = t;
4498
4499 return 0;
4500}
4501
6ea832a2 4502int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4503 assert(fd >= 0);
4504
6ea832a2
LP
4505 if (ioctl(fd, TIOCVHANGUP) < 0)
4506 return -errno;
4507
4508 return 0;
4509}
4510
4511int terminal_vhangup(const char *name) {
4512 int fd, r;
4513
4514 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4515 if (fd < 0)
4516 return fd;
4517
4518 r = terminal_vhangup_fd(fd);
4519 close_nointr_nofail(fd);
4520
4521 return r;
4522}
4523
4524int vt_disallocate(const char *name) {
4525 int fd, r;
4526 unsigned u;
6ea832a2
LP
4527
4528 /* Deallocate the VT if possible. If not possible
4529 * (i.e. because it is the active one), at least clear it
4530 * entirely (including the scrollback buffer) */
4531
b83bc4e9
LP
4532 if (!startswith(name, "/dev/"))
4533 return -EINVAL;
4534
4535 if (!tty_is_vc(name)) {
4536 /* So this is not a VT. I guess we cannot deallocate
4537 * it then. But let's at least clear the screen */
4538
4539 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4540 if (fd < 0)
4541 return fd;
4542
8585357a
LP
4543 loop_write(fd,
4544 "\033[r" /* clear scrolling region */
4545 "\033[H" /* move home */
4546 "\033[2J", /* clear screen */
4547 10, false);
b83bc4e9
LP
4548 close_nointr_nofail(fd);
4549
4550 return 0;
4551 }
6ea832a2
LP
4552
4553 if (!startswith(name, "/dev/tty"))
4554 return -EINVAL;
4555
4556 r = safe_atou(name+8, &u);
4557 if (r < 0)
4558 return r;
4559
4560 if (u <= 0)
b83bc4e9 4561 return -EINVAL;
6ea832a2 4562
b83bc4e9 4563 /* Try to deallocate */
6ea832a2
LP
4564 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4565 if (fd < 0)
4566 return fd;
4567
4568 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4569 close_nointr_nofail(fd);
6ea832a2 4570
b83bc4e9
LP
4571 if (r >= 0)
4572 return 0;
6ea832a2 4573
b83bc4e9 4574 if (errno != EBUSY)
6ea832a2 4575 return -errno;
6ea832a2 4576
b83bc4e9
LP
4577 /* Couldn't deallocate, so let's clear it fully with
4578 * scrollback */
4579 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4580 if (fd < 0)
b83bc4e9 4581 return fd;
6ea832a2 4582
8585357a
LP
4583 loop_write(fd,
4584 "\033[r" /* clear scrolling region */
4585 "\033[H" /* move home */
4586 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4587 10, false);
b83bc4e9 4588 close_nointr_nofail(fd);
6ea832a2 4589
b83bc4e9 4590 return 0;
6ea832a2
LP
4591}
4592
34ca941c
LP
4593int copy_file(const char *from, const char *to) {
4594 int r, fdf, fdt;
4595
4596 assert(from);
4597 assert(to);
4598
4599 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4600 if (fdf < 0)
4601 return -errno;
4602
4603 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4604 if (fdt < 0) {
4605 close_nointr_nofail(fdf);
4606 return -errno;
4607 }
4608
4609 for (;;) {
4610 char buf[PIPE_BUF];
4611 ssize_t n, k;
4612
4613 n = read(fdf, buf, sizeof(buf));
4614 if (n < 0) {
4615 r = -errno;
4616
4617 close_nointr_nofail(fdf);
4618 close_nointr(fdt);
4619 unlink(to);
4620
4621 return r;
4622 }
4623
4624 if (n == 0)
4625 break;
4626
4627 errno = 0;
4628 k = loop_write(fdt, buf, n, false);
4629 if (n != k) {
4630 r = k < 0 ? k : (errno ? -errno : -EIO);
4631
4632 close_nointr_nofail(fdf);
4633 close_nointr(fdt);
4634
4635 unlink(to);
4636 return r;
4637 }
4638 }
4639
4640 close_nointr_nofail(fdf);
4641 r = close_nointr(fdt);
4642
4643 if (r < 0) {
4644 unlink(to);
4645 return r;
4646 }
4647
4648 return 0;
4649}
4650
424a19f8
LP
4651int symlink_atomic(const char *from, const char *to) {
4652 char *x;
4653 _cleanup_free_ char *t;
34ca941c
LP
4654 const char *fn;
4655 size_t k;
4656 unsigned long long ull;
4657 unsigned i;
4658 int r;
4659
4660 assert(from);
4661 assert(to);
4662
4663 t = new(char, strlen(to) + 1 + 16 + 1);
4664 if (!t)
4665 return -ENOMEM;
4666
9eb977db 4667 fn = path_get_file_name(to);
34ca941c
LP
4668 k = fn-to;
4669 memcpy(t, to, k);
4670 t[k] = '.';
4671 x = stpcpy(t+k+1, fn);
4672
4673 ull = random_ull();
4674 for (i = 0; i < 16; i++) {
4675 *(x++) = hexchar(ull & 0xF);
4676 ull >>= 4;
4677 }
4678
4679 *x = 0;
4680
424a19f8
LP
4681 if (symlink(from, t) < 0)
4682 return -errno;
34ca941c
LP
4683
4684 if (rename(t, to) < 0) {
4685 r = -errno;
4686 unlink(t);
34ca941c
LP
4687 return r;
4688 }
4689
424a19f8 4690 return 0;
34ca941c
LP
4691}
4692
4d6d6518
LP
4693bool display_is_local(const char *display) {
4694 assert(display);
4695
4696 return
4697 display[0] == ':' &&
4698 display[1] >= '0' &&
4699 display[1] <= '9';
4700}
4701
4702int socket_from_display(const char *display, char **path) {
4703 size_t k;
4704 char *f, *c;
4705
4706 assert(display);
4707 assert(path);
4708
4709 if (!display_is_local(display))
4710 return -EINVAL;
4711
4712 k = strspn(display+1, "0123456789");
4713
4714 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4715 if (!f)
4716 return -ENOMEM;
4717
4718 c = stpcpy(f, "/tmp/.X11-unix/X");
4719 memcpy(c, display+1, k);
4720 c[k] = 0;
4721
4722 *path = f;
4723
4724 return 0;
4725}
4726
d05c5031
LP
4727int get_user_creds(
4728 const char **username,
4729 uid_t *uid, gid_t *gid,
4730 const char **home,
4731 const char **shell) {
4732
1cccf435 4733 struct passwd *p;
ddd88763 4734 uid_t u;
1cccf435
MV
4735
4736 assert(username);
4737 assert(*username);
1cccf435
MV
4738
4739 /* We enforce some special rules for uid=0: in order to avoid
4740 * NSS lookups for root we hardcode its data. */
4741
4742 if (streq(*username, "root") || streq(*username, "0")) {
4743 *username = "root";
4b67834e
LP
4744
4745 if (uid)
4746 *uid = 0;
4747
4748 if (gid)
4749 *gid = 0;
4750
4751 if (home)
4752 *home = "/root";
d05c5031
LP
4753
4754 if (shell)
4755 *shell = "/bin/sh";
4756
1cccf435
MV
4757 return 0;
4758 }
4759
ddd88763 4760 if (parse_uid(*username, &u) >= 0) {
1cccf435 4761 errno = 0;
ddd88763 4762 p = getpwuid(u);
1cccf435
MV
4763
4764 /* If there are multiple users with the same id, make
4765 * sure to leave $USER to the configured value instead
4766 * of the first occurrence in the database. However if
4767 * the uid was configured by a numeric uid, then let's
4768 * pick the real username from /etc/passwd. */
4769 if (p)
4770 *username = p->pw_name;
4771 } else {
4772 errno = 0;
4773 p = getpwnam(*username);
4774 }
4775
4776 if (!p)
4777 return errno != 0 ? -errno : -ESRCH;
4778
4b67834e
LP
4779 if (uid)
4780 *uid = p->pw_uid;
4781
4782 if (gid)
4783 *gid = p->pw_gid;
4784
4785 if (home)
4786 *home = p->pw_dir;
4787
d05c5031
LP
4788 if (shell)
4789 *shell = p->pw_shell;
4790
4b67834e
LP
4791 return 0;
4792}
4793
4794int get_group_creds(const char **groupname, gid_t *gid) {
4795 struct group *g;
4796 gid_t id;
4797
4798 assert(groupname);
4799
4800 /* We enforce some special rules for gid=0: in order to avoid
4801 * NSS lookups for root we hardcode its data. */
4802
4803 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4804 *groupname = "root";
4805
4806 if (gid)
4807 *gid = 0;
4808
4809 return 0;
4810 }
4811
4812 if (parse_gid(*groupname, &id) >= 0) {
4813 errno = 0;
4814 g = getgrgid(id);
4815
4816 if (g)
4817 *groupname = g->gr_name;
4818 } else {
4819 errno = 0;
4820 g = getgrnam(*groupname);
4821 }
4822
4823 if (!g)
4824 return errno != 0 ? -errno : -ESRCH;
4825
4826 if (gid)
4827 *gid = g->gr_gid;
4828
1cccf435
MV
4829 return 0;
4830}
4831
43673799
LP
4832int in_group(const char *name) {
4833 gid_t gid, *gids;
4834 int ngroups_max, r, i;
4835
4836 r = get_group_creds(&name, &gid);
4837 if (r < 0)
4838 return r;
4839
4840 if (getgid() == gid)
4841 return 1;
4842
4843 if (getegid() == gid)
4844 return 1;
4845
4846 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4847 assert(ngroups_max > 0);
4848
4849 gids = alloca(sizeof(gid_t) * ngroups_max);
4850
4851 r = getgroups(ngroups_max, gids);
4852 if (r < 0)
4853 return -errno;
4854
4855 for (i = 0; i < r; i++)
4856 if (gids[i] == gid)
4857 return 1;
4858
4859 return 0;
4860}
4861
8092a428
LP
4862int glob_exists(const char *path) {
4863 glob_t g;
4864 int r, k;
4865
4866 assert(path);
4867
4868 zero(g);
4869 errno = 0;
4870 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4871
4872 if (k == GLOB_NOMATCH)
4873 r = 0;
4874 else if (k == GLOB_NOSPACE)
4875 r = -ENOMEM;
4876 else if (k == 0)
4877 r = !strv_isempty(g.gl_pathv);
4878 else
4879 r = errno ? -errno : -EIO;
4880
4881 globfree(&g);
4882
4883 return r;
4884}
4885
83096483
LP
4886int dirent_ensure_type(DIR *d, struct dirent *de) {
4887 struct stat st;
4888
4889 assert(d);
4890 assert(de);
4891
4892 if (de->d_type != DT_UNKNOWN)
4893 return 0;
4894
4895 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4896 return -errno;
4897
4898 de->d_type =
4899 S_ISREG(st.st_mode) ? DT_REG :
4900 S_ISDIR(st.st_mode) ? DT_DIR :
4901 S_ISLNK(st.st_mode) ? DT_LNK :
4902 S_ISFIFO(st.st_mode) ? DT_FIFO :
4903 S_ISSOCK(st.st_mode) ? DT_SOCK :
4904 S_ISCHR(st.st_mode) ? DT_CHR :
4905 S_ISBLK(st.st_mode) ? DT_BLK :
4906 DT_UNKNOWN;
4907
4908 return 0;
4909}
4910
4911int in_search_path(const char *path, char **search) {
4912 char **i, *parent;
4913 int r;
4914
9eb977db 4915 r = path_get_parent(path, &parent);
83096483
LP
4916 if (r < 0)
4917 return r;
4918
4919 r = 0;
4920
4921 STRV_FOREACH(i, search) {
4922 if (path_equal(parent, *i)) {
4923 r = 1;
4924 break;
4925 }
4926 }
4927
4928 free(parent);
4929
4930 return r;
4931}
4932
034a2a52
LP
4933int get_files_in_directory(const char *path, char ***list) {
4934 DIR *d;
4935 int r = 0;
4936 unsigned n = 0;
4937 char **l = NULL;
4938
4939 assert(path);
d60ef526
LP
4940
4941 /* Returns all files in a directory in *list, and the number
4942 * of files as return value. If list is NULL returns only the
4943 * number */
034a2a52
LP
4944
4945 d = opendir(path);
8ea913b2
LP
4946 if (!d)
4947 return -errno;
4948
034a2a52 4949 for (;;) {
7d5e9c0f
LP
4950 struct dirent *de;
4951 union dirent_storage buf;
034a2a52
LP
4952 int k;
4953
7d5e9c0f 4954 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
4955 if (k != 0) {
4956 r = -k;
4957 goto finish;
4958 }
4959
4960 if (!de)
4961 break;
4962
4963 dirent_ensure_type(d, de);
4964
4965 if (!dirent_is_file(de))
4966 continue;
4967
d60ef526
LP
4968 if (list) {
4969 if ((unsigned) r >= n) {
4970 char **t;
034a2a52 4971
d60ef526
LP
4972 n = MAX(16, 2*r);
4973 t = realloc(l, sizeof(char*) * n);
4974 if (!t) {
4975 r = -ENOMEM;
4976 goto finish;
4977 }
034a2a52 4978
d60ef526
LP
4979 l = t;
4980 }
034a2a52 4981
d60ef526 4982 assert((unsigned) r < n);
034a2a52 4983
d60ef526
LP
4984 l[r] = strdup(de->d_name);
4985 if (!l[r]) {
4986 r = -ENOMEM;
4987 goto finish;
4988 }
034a2a52 4989
d60ef526
LP
4990 l[++r] = NULL;
4991 } else
4992 r++;
034a2a52
LP
4993 }
4994
4995finish:
4996 if (d)
4997 closedir(d);
4998
d60ef526
LP
4999 if (r >= 0) {
5000 if (list)
5001 *list = l;
5002 } else
034a2a52
LP
5003 strv_free(l);
5004
5005 return r;
5006}
5007
b7def684 5008char *strjoin(const char *x, ...) {
911a4828
LP
5009 va_list ap;
5010 size_t l;
5011 char *r, *p;
5012
5013 va_start(ap, x);
5014
5015 if (x) {
5016 l = strlen(x);
5017
5018 for (;;) {
5019 const char *t;
040f18ea 5020 size_t n;
911a4828
LP
5021
5022 t = va_arg(ap, const char *);
5023 if (!t)
5024 break;
5025
040f18ea
LP
5026 n = strlen(t);
5027 if (n > ((size_t) -1) - l)
5028 return NULL;
5029
5030 l += n;
911a4828
LP
5031 }
5032 } else
5033 l = 0;
5034
5035 va_end(ap);
5036
5037 r = new(char, l+1);
5038 if (!r)
5039 return NULL;
5040
5041 if (x) {
5042 p = stpcpy(r, x);
5043
5044 va_start(ap, x);
5045
5046 for (;;) {
5047 const char *t;
5048
5049 t = va_arg(ap, const char *);
5050 if (!t)
5051 break;
5052
5053 p = stpcpy(p, t);
5054 }
8ea913b2
LP
5055
5056 va_end(ap);
911a4828
LP
5057 } else
5058 r[0] = 0;
5059
5060 return r;
5061}
5062
b636465b
LP
5063bool is_main_thread(void) {
5064 static __thread int cached = 0;
5065
5066 if (_unlikely_(cached == 0))
5067 cached = getpid() == gettid() ? 1 : -1;
5068
5069 return cached > 0;
5070}
5071
94959f0f
LP
5072int block_get_whole_disk(dev_t d, dev_t *ret) {
5073 char *p, *s;
5074 int r;
5075 unsigned n, m;
5076
5077 assert(ret);
5078
5079 /* If it has a queue this is good enough for us */
5080 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
5081 return -ENOMEM;
5082
5083 r = access(p, F_OK);
5084 free(p);
5085
5086 if (r >= 0) {
5087 *ret = d;
5088 return 0;
5089 }
5090
5091 /* If it is a partition find the originating device */
5092 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
5093 return -ENOMEM;
5094
5095 r = access(p, F_OK);
5096 free(p);
5097
5098 if (r < 0)
5099 return -ENOENT;
5100
5101 /* Get parent dev_t */
5102 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
5103 return -ENOMEM;
5104
5105 r = read_one_line_file(p, &s);
5106 free(p);
5107
5108 if (r < 0)
5109 return r;
5110
5111 r = sscanf(s, "%u:%u", &m, &n);
5112 free(s);
5113
5114 if (r != 2)
5115 return -EINVAL;
5116
5117 /* Only return this if it is really good enough for us. */
5118 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
5119 return -ENOMEM;
5120
5121 r = access(p, F_OK);
5122 free(p);
5123
5124 if (r >= 0) {
5125 *ret = makedev(m, n);
5126 return 0;
5127 }
5128
5129 return -ENOENT;
5130}
5131
8d53b453 5132int file_is_priv_sticky(const char *p) {
ad293f5a
LP
5133 struct stat st;
5134
5135 assert(p);
5136
5137 if (lstat(p, &st) < 0)
5138 return -errno;
5139
5140 return
8d53b453 5141 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
5142 (st.st_mode & S_ISVTX);
5143}
94959f0f 5144
f41607a6
LP
5145static const char *const ioprio_class_table[] = {
5146 [IOPRIO_CLASS_NONE] = "none",
5147 [IOPRIO_CLASS_RT] = "realtime",
5148 [IOPRIO_CLASS_BE] = "best-effort",
5149 [IOPRIO_CLASS_IDLE] = "idle"
5150};
5151
5152DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5153
5154static const char *const sigchld_code_table[] = {
5155 [CLD_EXITED] = "exited",
5156 [CLD_KILLED] = "killed",
5157 [CLD_DUMPED] = "dumped",
5158 [CLD_TRAPPED] = "trapped",
5159 [CLD_STOPPED] = "stopped",
5160 [CLD_CONTINUED] = "continued",
5161};
5162
5163DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5164
5165static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5166 [LOG_FAC(LOG_KERN)] = "kern",
5167 [LOG_FAC(LOG_USER)] = "user",
5168 [LOG_FAC(LOG_MAIL)] = "mail",
5169 [LOG_FAC(LOG_DAEMON)] = "daemon",
5170 [LOG_FAC(LOG_AUTH)] = "auth",
5171 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5172 [LOG_FAC(LOG_LPR)] = "lpr",
5173 [LOG_FAC(LOG_NEWS)] = "news",
5174 [LOG_FAC(LOG_UUCP)] = "uucp",
5175 [LOG_FAC(LOG_CRON)] = "cron",
5176 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5177 [LOG_FAC(LOG_FTP)] = "ftp",
5178 [LOG_FAC(LOG_LOCAL0)] = "local0",
5179 [LOG_FAC(LOG_LOCAL1)] = "local1",
5180 [LOG_FAC(LOG_LOCAL2)] = "local2",
5181 [LOG_FAC(LOG_LOCAL3)] = "local3",
5182 [LOG_FAC(LOG_LOCAL4)] = "local4",
5183 [LOG_FAC(LOG_LOCAL5)] = "local5",
5184 [LOG_FAC(LOG_LOCAL6)] = "local6",
5185 [LOG_FAC(LOG_LOCAL7)] = "local7"
5186};
5187
5188DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5189
5190static const char *const log_level_table[] = {
5191 [LOG_EMERG] = "emerg",
5192 [LOG_ALERT] = "alert",
5193 [LOG_CRIT] = "crit",
5194 [LOG_ERR] = "err",
5195 [LOG_WARNING] = "warning",
5196 [LOG_NOTICE] = "notice",
5197 [LOG_INFO] = "info",
5198 [LOG_DEBUG] = "debug"
5199};
5200
5201DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5202
5203static const char* const sched_policy_table[] = {
5204 [SCHED_OTHER] = "other",
5205 [SCHED_BATCH] = "batch",
5206 [SCHED_IDLE] = "idle",
5207 [SCHED_FIFO] = "fifo",
5208 [SCHED_RR] = "rr"
5209};
5210
5211DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5212
5213static const char* const rlimit_table[] = {
5214 [RLIMIT_CPU] = "LimitCPU",
5215 [RLIMIT_FSIZE] = "LimitFSIZE",
5216 [RLIMIT_DATA] = "LimitDATA",
5217 [RLIMIT_STACK] = "LimitSTACK",
5218 [RLIMIT_CORE] = "LimitCORE",
5219 [RLIMIT_RSS] = "LimitRSS",
5220 [RLIMIT_NOFILE] = "LimitNOFILE",
5221 [RLIMIT_AS] = "LimitAS",
5222 [RLIMIT_NPROC] = "LimitNPROC",
5223 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5224 [RLIMIT_LOCKS] = "LimitLOCKS",
5225 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5226 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5227 [RLIMIT_NICE] = "LimitNICE",
5228 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5229 [RLIMIT_RTTIME] = "LimitRTTIME"
5230};
5231
5232DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5233
5234static const char* const ip_tos_table[] = {
5235 [IPTOS_LOWDELAY] = "low-delay",
5236 [IPTOS_THROUGHPUT] = "throughput",
5237 [IPTOS_RELIABILITY] = "reliability",
5238 [IPTOS_LOWCOST] = "low-cost",
5239};
5240
5241DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5242
4e240ab0 5243static const char *const __signal_table[] = {
f41607a6
LP
5244 [SIGHUP] = "HUP",
5245 [SIGINT] = "INT",
5246 [SIGQUIT] = "QUIT",
5247 [SIGILL] = "ILL",
5248 [SIGTRAP] = "TRAP",
5249 [SIGABRT] = "ABRT",
5250 [SIGBUS] = "BUS",
5251 [SIGFPE] = "FPE",
5252 [SIGKILL] = "KILL",
5253 [SIGUSR1] = "USR1",
5254 [SIGSEGV] = "SEGV",
5255 [SIGUSR2] = "USR2",
5256 [SIGPIPE] = "PIPE",
5257 [SIGALRM] = "ALRM",
5258 [SIGTERM] = "TERM",
5259#ifdef SIGSTKFLT
5260 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5261#endif
5262 [SIGCHLD] = "CHLD",
5263 [SIGCONT] = "CONT",
5264 [SIGSTOP] = "STOP",
5265 [SIGTSTP] = "TSTP",
5266 [SIGTTIN] = "TTIN",
5267 [SIGTTOU] = "TTOU",
5268 [SIGURG] = "URG",
5269 [SIGXCPU] = "XCPU",
5270 [SIGXFSZ] = "XFSZ",
5271 [SIGVTALRM] = "VTALRM",
5272 [SIGPROF] = "PROF",
5273 [SIGWINCH] = "WINCH",
5274 [SIGIO] = "IO",
5275 [SIGPWR] = "PWR",
5276 [SIGSYS] = "SYS"
5277};
5278
4e240ab0
MS
5279DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5280
5281const char *signal_to_string(int signo) {
5282 static __thread char buf[12];
5283 const char *name;
5284
5285 name = __signal_to_string(signo);
5286 if (name)
5287 return name;
5288
5289 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
5290 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
5291 else
5292 snprintf(buf, sizeof(buf) - 1, "%d", signo);
5293 char_array_0(buf);
5294 return buf;
5295}
5296
5297int signal_from_string(const char *s) {
5298 int signo;
5299 int offset = 0;
5300 unsigned u;
5301
040f18ea 5302 signo = __signal_from_string(s);
4e240ab0
MS
5303 if (signo > 0)
5304 return signo;
5305
5306 if (startswith(s, "RTMIN+")) {
5307 s += 6;
5308 offset = SIGRTMIN;
5309 }
5310 if (safe_atou(s, &u) >= 0) {
5311 signo = (int) u + offset;
5312 if (signo > 0 && signo < _NSIG)
5313 return signo;
5314 }
5315 return -1;
5316}
65457142
FC
5317
5318bool kexec_loaded(void) {
5319 bool loaded = false;
5320 char *s;
5321
5322 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5323 if (s[0] == '1')
5324 loaded = true;
5325 free(s);
5326 }
5327 return loaded;
5328}
fb9de93d
LP
5329
5330int strdup_or_null(const char *a, char **b) {
5331 char *c;
5332
5333 assert(b);
5334
5335 if (!a) {
5336 *b = NULL;
5337 return 0;
5338 }
5339
5340 c = strdup(a);
5341 if (!c)
5342 return -ENOMEM;
5343
5344 *b = c;
5345 return 0;
5346}
64685e0c 5347
87d2c1ff
LP
5348int prot_from_flags(int flags) {
5349
5350 switch (flags & O_ACCMODE) {
5351
5352 case O_RDONLY:
5353 return PROT_READ;
5354
5355 case O_WRONLY:
5356 return PROT_WRITE;
5357
5358 case O_RDWR:
5359 return PROT_READ|PROT_WRITE;
5360
5361 default:
5362 return -EINVAL;
5363 }
7c99e0c1 5364}
689b9a22 5365
babfc091 5366char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5367 unsigned i;
babfc091
LP
5368
5369 static const struct {
5370 const char *suffix;
5371 off_t factor;
5372 } table[] = {
32895bb3
LP
5373 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5374 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5375 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5376 { "G", 1024ULL*1024ULL*1024ULL },
5377 { "M", 1024ULL*1024ULL },
5378 { "K", 1024ULL },
5379 };
5380
5381 for (i = 0; i < ELEMENTSOF(table); i++) {
5382
5383 if (t >= table[i].factor) {
5384 snprintf(buf, l,
5385 "%llu.%llu%s",
5386 (unsigned long long) (t / table[i].factor),
5387 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5388 table[i].suffix);
5389
5390 goto finish;
5391 }
5392 }
5393
5394 snprintf(buf, l, "%lluB", (unsigned long long) t);
5395
5396finish:
5397 buf[l-1] = 0;
5398 return buf;
5399
5400}
55d7bfc1
LP
5401
5402void* memdup(const void *p, size_t l) {
5403 void *r;
5404
5405 assert(p);
5406
5407 r = malloc(l);
5408 if (!r)
5409 return NULL;
5410
5411 memcpy(r, p, l);
5412 return r;
5413}
bb99a35a
LP
5414
5415int fd_inc_sndbuf(int fd, size_t n) {
5416 int r, value;
5417 socklen_t l = sizeof(value);
5418
5419 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
5420 if (r >= 0 &&
5421 l == sizeof(value) &&
5422 (size_t) value >= n*2)
5423 return 0;
5424
5425 value = (int) n;
5426 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
5427 if (r < 0)
5428 return -errno;
5429
5430 return 1;
5431}
5432
5433int fd_inc_rcvbuf(int fd, size_t n) {
5434 int r, value;
5435 socklen_t l = sizeof(value);
5436
5437 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
5438 if (r >= 0 &&
5439 l == sizeof(value) &&
5440 (size_t) value >= n*2)
5441 return 0;
5442
5443 value = (int) n;
5444 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
5445 if (r < 0)
5446 return -errno;
5447
5448 return 1;
5449}
6bb92a16 5450
9bdc770c 5451int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
5452 pid_t parent_pid, agent_pid;
5453 int fd;
5454 bool stdout_is_tty, stderr_is_tty;
5455 unsigned n, i;
5456 va_list ap;
5457 char **l;
5458
5459 assert(pid);
5460 assert(path);
5461
5462 parent_pid = getpid();
5463
5464 /* Spawns a temporary TTY agent, making sure it goes away when
5465 * we go away */
5466
5467 agent_pid = fork();
5468 if (agent_pid < 0)
5469 return -errno;
5470
5471 if (agent_pid != 0) {
5472 *pid = agent_pid;
5473 return 0;
5474 }
5475
5476 /* In the child:
5477 *
5478 * Make sure the agent goes away when the parent dies */
5479 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5480 _exit(EXIT_FAILURE);
5481
5482 /* Check whether our parent died before we were able
5483 * to set the death signal */
5484 if (getppid() != parent_pid)
5485 _exit(EXIT_SUCCESS);
5486
5487 /* Don't leak fds to the agent */
9bdc770c 5488 close_all_fds(except, n_except);
6bb92a16
LP
5489
5490 stdout_is_tty = isatty(STDOUT_FILENO);
5491 stderr_is_tty = isatty(STDERR_FILENO);
5492
5493 if (!stdout_is_tty || !stderr_is_tty) {
5494 /* Detach from stdout/stderr. and reopen
5495 * /dev/tty for them. This is important to
5496 * ensure that when systemctl is started via
5497 * popen() or a similar call that expects to
5498 * read EOF we actually do generate EOF and
5499 * not delay this indefinitely by because we
5500 * keep an unused copy of stdin around. */
5501 fd = open("/dev/tty", O_WRONLY);
5502 if (fd < 0) {
5503 log_error("Failed to open /dev/tty: %m");
5504 _exit(EXIT_FAILURE);
5505 }
5506
5507 if (!stdout_is_tty)
5508 dup2(fd, STDOUT_FILENO);
5509
5510 if (!stderr_is_tty)
5511 dup2(fd, STDERR_FILENO);
5512
5513 if (fd > 2)
5514 close(fd);
5515 }
5516
5517 /* Count arguments */
5518 va_start(ap, path);
5519 for (n = 0; va_arg(ap, char*); n++)
5520 ;
5521 va_end(ap);
5522
5523 /* Allocate strv */
5524 l = alloca(sizeof(char *) * (n + 1));
5525
5526 /* Fill in arguments */
5527 va_start(ap, path);
5528 for (i = 0; i <= n; i++)
5529 l[i] = va_arg(ap, char*);
5530 va_end(ap);
5531
5532 execv(path, l);
5533 _exit(EXIT_FAILURE);
5534}
68faf98c
LP
5535
5536int setrlimit_closest(int resource, const struct rlimit *rlim) {
5537 struct rlimit highest, fixed;
5538
5539 assert(rlim);
5540
5541 if (setrlimit(resource, rlim) >= 0)
5542 return 0;
5543
5544 if (errno != EPERM)
5545 return -errno;
5546
5547 /* So we failed to set the desired setrlimit, then let's try
5548 * to get as close as we can */
5549 assert_se(getrlimit(resource, &highest) == 0);
5550
5551 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5552 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5553
5554 if (setrlimit(resource, &fixed) < 0)
5555 return -errno;
5556
5557 return 0;
5558}
3d9a4122 5559
ab94af92
LP
5560int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5561 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5562 int r;
5563 FILE *f;
5564 bool done = false;
5565 size_t l;
5566
5567 assert(field);
5568 assert(_value);
5569
5570 if (pid == 0)
5571 pid = getpid();
5572
5573 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5574 char_array_0(path);
5575
5576 f = fopen(path, "re");
5577 if (!f)
5578 return -errno;
5579
5580 l = strlen(field);
5581 r = 0;
5582
5583 do {
5584 char line[LINE_MAX];
5585 unsigned i;
5586
5587 for (i = 0; i < sizeof(line)-1; i++) {
5588 int c;
5589
5590 c = getc(f);
5591 if (_unlikely_(c == EOF)) {
5592 done = true;
5593 break;
5594 } else if (c == 0)
5595 break;
5596
5597 line[i] = c;
5598 }
5599 line[i] = 0;
5600
5601 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5602 value = strdup(line + l + 1);
5603 if (!value) {
5604 r = -ENOMEM;
5605 break;
5606 }
5607
5608 r = 1;
5609 break;
5610 }
5611
5612 } while (!done);
5613
5614 fclose(f);
5615
5616 if (r >= 0)
5617 *_value = value;
5618
5619 return r;
5620}
d889a206
LP
5621
5622int can_sleep(const char *type) {
e67f47e5 5623 char *w, *state;
d889a206 5624 size_t l, k;
d889a206 5625 int r;
e67f47e5 5626 _cleanup_free_ char *p = NULL;
d889a206
LP
5627
5628 assert(type);
5629
5630 r = read_one_line_file("/sys/power/state", &p);
5631 if (r < 0)
5632 return r == -ENOENT ? 0 : r;
5633
5634 k = strlen(type);
e67f47e5
LP
5635 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
5636 if (l == k && memcmp(w, type, l) == 0)
5637 return true;
d889a206 5638
e67f47e5 5639 return false;
d889a206 5640}
49dbfa7b
LP
5641
5642bool is_valid_documentation_url(const char *url) {
5643 assert(url);
5644
5645 if (startswith(url, "http://") && url[7])
5646 return true;
5647
5648 if (startswith(url, "https://") && url[8])
5649 return true;
5650
5651 if (startswith(url, "file:") && url[5])
5652 return true;
5653
5654 if (startswith(url, "info:") && url[5])
5655 return true;
5656
5657 if (startswith(url, "man:") && url[4])
5658 return true;
5659
5660 return false;
5661}
9be346c9
HH
5662
5663bool in_initrd(void) {
a05f97b3 5664 static __thread int saved = -1;
825c6fe5 5665 struct statfs s;
8f33b5b8 5666
825c6fe5
LP
5667 if (saved >= 0)
5668 return saved;
5669
5670 /* We make two checks here:
5671 *
5672 * 1. the flag file /etc/initrd-release must exist
5673 * 2. the root file system must be a memory file system
5674 *
5675 * The second check is extra paranoia, since misdetecting an
5676 * initrd can have bad bad consequences due the initrd
5677 * emptying when transititioning to the main systemd.
5678 */
5679
5680 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5681 statfs("/", &s) >= 0 &&
5682 (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
9be346c9 5683
8f33b5b8 5684 return saved;
9be346c9 5685}
069cfc85
LP
5686
5687void warn_melody(void) {
e67f47e5 5688 _cleanup_close_ int fd = -1;
069cfc85
LP
5689
5690 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5691 if (fd < 0)
5692 return;
5693
040f18ea 5694 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5695
5696 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5697 usleep(125*USEC_PER_MSEC);
5698
5699 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5700 usleep(125*USEC_PER_MSEC);
5701
5702 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5703 usleep(125*USEC_PER_MSEC);
5704
5705 ioctl(fd, KIOCSOUND, 0);
069cfc85 5706}
cd3bd60a
LP
5707
5708int make_console_stdio(void) {
5709 int fd, r;
5710
5711 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5712
5713 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5714 if (fd < 0) {
5715 log_error("Failed to acquire terminal: %s", strerror(-fd));
5716 return fd;
5717 }
5718
5719 r = make_stdio(fd);
5720 if (r < 0) {
5721 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5722 return r;
5723 }
5724
5725 return 0;
5726}
7c5f152a
LP
5727
5728int get_home_dir(char **_h) {
5729 char *h;
5730 const char *e;
5731 uid_t u;
5732 struct passwd *p;
5733
5734 assert(_h);
5735
5736 /* Take the user specified one */
5737 e = getenv("HOME");
5738 if (e) {
5739 h = strdup(e);
5740 if (!h)
5741 return -ENOMEM;
5742
5743 *_h = h;
5744 return 0;
5745 }
5746
5747 /* Hardcode home directory for root to avoid NSS */
5748 u = getuid();
5749 if (u == 0) {
5750 h = strdup("/root");
5751 if (!h)
5752 return -ENOMEM;
5753
5754 *_h = h;
5755 return 0;
5756 }
5757
5758 /* Check the database... */
5759 errno = 0;
5760 p = getpwuid(u);
5761 if (!p)
e67f47e5 5762 return errno ? -errno : -ESRCH;
7c5f152a
LP
5763
5764 if (!path_is_absolute(p->pw_dir))
5765 return -EINVAL;
5766
5767 h = strdup(p->pw_dir);
5768 if (!h)
5769 return -ENOMEM;
5770
5771 *_h = h;
5772 return 0;
5773}
5774
5775int get_shell(char **_sh) {
5776 char *sh;
5777 const char *e;
5778 uid_t u;
5779 struct passwd *p;
5780
5781 assert(_sh);
5782
5783 /* Take the user specified one */
5784 e = getenv("SHELL");
5785 if (e) {
5786 sh = strdup(e);
5787 if (!sh)
5788 return -ENOMEM;
5789
5790 *_sh = sh;
5791 return 0;
5792 }
5793
5794 /* Hardcode home directory for root to avoid NSS */
5795 u = getuid();
5796 if (u == 0) {
5797 sh = strdup("/bin/sh");
5798 if (!sh)
5799 return -ENOMEM;
5800
5801 *_sh = sh;
5802 return 0;
5803 }
5804
5805 /* Check the database... */
5806 errno = 0;
5807 p = getpwuid(u);
5808 if (!p)
5809 return errno ? -errno : -ESRCH;
5810
5811 if (!path_is_absolute(p->pw_shell))
5812 return -EINVAL;
5813
5814 sh = strdup(p->pw_shell);
5815 if (!sh)
5816 return -ENOMEM;
5817
5818 *_sh = sh;
5819 return 0;
5820}
2fbe635a
LP
5821
5822void freep(void *p) {
5823 free(*(void**) p);
5824}
5825
5826void fclosep(FILE **f) {
5827 if (*f)
5828 fclose(*f);
5829}
e67f47e5
LP
5830
5831void closep(int *fd) {
5832 if (*fd >= 0)
5833 close_nointr_nofail(*fd);
5834}
a05f97b3
LP
5835
5836void closedirp(DIR **d) {
5837 if (*d)
5838 closedir(*d);
5839}
25ea79fe
ZJS
5840
5841void umaskp(mode_t *u) {
5842 umask(*u);
5843}