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