]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
util: make sure heap allocators fail when array allocations are out of bounds
[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 (;;) {
7d5e9c0f
LP
2959 struct dirent *de;
2960 union dirent_storage buf;
01f78473 2961
7d5e9c0f 2962 r = readdir_r(d, &buf.de, &de);
a05f97b3
LP
2963 if (r > 0)
2964 return -r;
01f78473 2965
a05f97b3
LP
2966 if (!de)
2967 return 1;
01f78473 2968
a05f97b3
LP
2969 if (!ignore_file(de->d_name))
2970 return 0;
2971 }
01f78473
LP
2972}
2973
d3782d60 2974unsigned long long random_ull(void) {
a05f97b3 2975 _cleanup_close_ int fd;
d3782d60
LP
2976 uint64_t ull;
2977 ssize_t r;
2978
ac0930c8
LP
2979 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
2980 if (fd < 0)
d3782d60
LP
2981 goto fallback;
2982
eb22ac37 2983 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
2984 if (r != sizeof(ull))
2985 goto fallback;
2986
2987 return ull;
2988
2989fallback:
2990 return random() * RAND_MAX + random();
2991}
2992
5b6319dc
LP
2993void rename_process(const char name[8]) {
2994 assert(name);
2995
5d6b1584
LP
2996 /* This is a like a poor man's setproctitle(). It changes the
2997 * comm field, argv[0], and also the glibc's internally used
2998 * name of the process. For the first one a limit of 16 chars
2999 * applies, to the second one usually one of 10 (i.e. length
3000 * of "/sbin/init"), to the third one one of 7 (i.e. length of
3001 * "systemd"). If you pass a longer string it will be
3002 * truncated */
5b6319dc 3003
5d6b1584 3004 prctl(PR_SET_NAME, name);
5b6319dc
LP
3005
3006 if (program_invocation_name)
3007 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
3008
3009 if (saved_argc > 0) {
3010 int i;
3011
3012 if (saved_argv[0])
3013 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
3014
3015 for (i = 1; i < saved_argc; i++) {
3016 if (!saved_argv[i])
3017 break;
3018
3019 memset(saved_argv[i], 0, strlen(saved_argv[i]));
3020 }
3021 }
5b6319dc
LP
3022}
3023
7d793605
LP
3024void sigset_add_many(sigset_t *ss, ...) {
3025 va_list ap;
3026 int sig;
3027
3028 assert(ss);
3029
3030 va_start(ap, ss);
3031 while ((sig = va_arg(ap, int)) > 0)
3032 assert_se(sigaddset(ss, sig) == 0);
3033 va_end(ap);
3034}
3035
ef2f1067
LP
3036char* gethostname_malloc(void) {
3037 struct utsname u;
3038
3039 assert_se(uname(&u) >= 0);
3040
344de609 3041 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
3042 return strdup(u.nodename);
3043
3044 return strdup(u.sysname);
3045}
3046
344de609
LP
3047bool hostname_is_set(void) {
3048 struct utsname u;
3049
3050 assert_se(uname(&u) >= 0);
3051
3052 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
3053}
3054
7c5f152a 3055static char *lookup_uid(uid_t uid) {
ef2f1067 3056 long bufsize;
a05f97b3
LP
3057 char *name;
3058 _cleanup_free_ char *buf = NULL;
ef2f1067 3059 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
3060
3061 /* Shortcut things to avoid NSS lookups */
3062 if (uid == 0)
3063 return strdup("root");
3064
7c5f152a
LP
3065 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
3066 if (bufsize <= 0)
ef2f1067
LP
3067 bufsize = 4096;
3068
7c5f152a
LP
3069 buf = malloc(bufsize);
3070 if (!buf)
ef2f1067
LP
3071 return NULL;
3072
a05f97b3
LP
3073 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
3074 return strdup(pw->pw_name);
ef2f1067
LP
3075
3076 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
3077 return NULL;
3078
3079 return name;
3080}
3081
7c5f152a
LP
3082char* getlogname_malloc(void) {
3083 uid_t uid;
3084 struct stat st;
3085
3086 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
3087 uid = st.st_uid;
3088 else
3089 uid = getuid();
3090
3091 return lookup_uid(uid);
3092}
3093
3094char *getusername_malloc(void) {
3095 const char *e;
3096
3097 e = getenv("USER");
3098 if (e)
3099 return strdup(e);
3100
3101 return lookup_uid(getuid());
3102}
3103
fc116c6a
LP
3104int getttyname_malloc(int fd, char **r) {
3105 char path[PATH_MAX], *c;
618e02c7 3106 int k;
8c6db833
LP
3107
3108 assert(r);
ef2f1067 3109
a05f97b3
LP
3110 k = ttyname_r(fd, path, sizeof(path));
3111 if (k != 0)
618e02c7 3112 return -k;
ef2f1067
LP
3113
3114 char_array_0(path);
3115
a05f97b3
LP
3116 c = strdup(startswith(path, "/dev/") ? path + 5 : path);
3117 if (!c)
8c6db833
LP
3118 return -ENOMEM;
3119
3120 *r = c;
3121 return 0;
3122}
3123
fc116c6a
LP
3124int getttyname_harder(int fd, char **r) {
3125 int k;
3126 char *s;
3127
a05f97b3
LP
3128 k = getttyname_malloc(fd, &s);
3129 if (k < 0)
fc116c6a
LP
3130 return k;
3131
3132 if (streq(s, "tty")) {
3133 free(s);
4d6d6518 3134 return get_ctty(0, NULL, r);
fc116c6a
LP
3135 }
3136
3137 *r = s;
3138 return 0;
3139}
3140
4d6d6518 3141int get_ctty_devnr(pid_t pid, dev_t *d) {
fc116c6a 3142 int k;
4d6d6518 3143 char line[LINE_MAX], *p, *fn;
fc116c6a
LP
3144 unsigned long ttynr;
3145 FILE *f;
3146
4d6d6518
LP
3147 if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
3148 return -ENOMEM;
3149
3150 f = fopen(fn, "re");
3151 free(fn);
3152 if (!f)
fc116c6a
LP
3153 return -errno;
3154
4d6d6518 3155 if (!fgets(line, sizeof(line), f)) {
35d50f55 3156 k = feof(f) ? -EIO : -errno;
fc116c6a
LP
3157 fclose(f);
3158 return k;
3159 }
3160
3161 fclose(f);
3162
4d6d6518
LP
3163 p = strrchr(line, ')');
3164 if (!p)
fc116c6a
LP
3165 return -EIO;
3166
3167 p++;
3168
3169 if (sscanf(p, " "
3170 "%*c " /* state */
3171 "%*d " /* ppid */
3172 "%*d " /* pgrp */
3173 "%*d " /* session */
3174 "%lu ", /* ttynr */
3175 &ttynr) != 1)
3176 return -EIO;
3177
3178 *d = (dev_t) ttynr;
3179 return 0;
3180}
3181
4d6d6518 3182int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 3183 int k;
20c03b7b 3184 char fn[PATH_MAX], *s, *b, *p;
fc116c6a
LP
3185 dev_t devnr;
3186
3187 assert(r);
3188
4d6d6518
LP
3189 k = get_ctty_devnr(pid, &devnr);
3190 if (k < 0)
fc116c6a
LP
3191 return k;
3192
3193 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
3194 char_array_0(fn);
3195
3196 if ((k = readlink_malloc(fn, &s)) < 0) {
3197
3198 if (k != -ENOENT)
3199 return k;
3200
46824d0e
LP
3201 /* This is an ugly hack */
3202 if (major(devnr) == 136) {
3203 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
3204 return -ENOMEM;
3205
3206 *r = b;
3207 if (_devnr)
3208 *_devnr = devnr;
3209
3210 return 0;
3211 }
3212
fc116c6a
LP
3213 /* Probably something like the ptys which have no
3214 * symlink in /dev/char. Let's return something
3215 * vaguely useful. */
3216
3217 if (!(b = strdup(fn + 5)))
3218 return -ENOMEM;
3219
3220 *r = b;
46824d0e
LP
3221 if (_devnr)
3222 *_devnr = devnr;
3223
fc116c6a
LP
3224 return 0;
3225 }
3226
3227 if (startswith(s, "/dev/"))
3228 p = s + 5;
3229 else if (startswith(s, "../"))
3230 p = s + 3;
3231 else
3232 p = s;
3233
3234 b = strdup(p);
3235 free(s);
3236
3237 if (!b)
3238 return -ENOMEM;
3239
3240 *r = b;
46824d0e
LP
3241 if (_devnr)
3242 *_devnr = devnr;
3243
fc116c6a
LP
3244 return 0;
3245}
3246
f56d5db9 3247int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
3248 DIR *d;
3249 int ret = 0;
3250
3251 assert(fd >= 0);
3252
3253 /* This returns the first error we run into, but nevertheless
7925c22a 3254 * tries to go on. This closes the passed fd. */
8c6db833 3255
d4d046e3
LP
3256 d = fdopendir(fd);
3257 if (!d) {
8c6db833 3258 close_nointr_nofail(fd);
4c633005
LP
3259
3260 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
3261 }
3262
3263 for (;;) {
7d5e9c0f
LP
3264 struct dirent *de;
3265 union dirent_storage buf;
7925c22a
LP
3266 bool is_dir, keep_around;
3267 struct stat st;
8c6db833
LP
3268 int r;
3269
7d5e9c0f 3270 r = readdir_r(d, &buf.de, &de);
d4d046e3
LP
3271 if (r != 0 && ret == 0) {
3272 ret = -r;
8c6db833
LP
3273 break;
3274 }
3275
3276 if (!de)
3277 break;
3278
3279 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
3280 continue;
3281
7925c22a
LP
3282 if (de->d_type == DT_UNKNOWN ||
3283 honour_sticky ||
3284 (de->d_type == DT_DIR && root_dev)) {
8c6db833 3285 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 3286 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3287 ret = -errno;
3288 continue;
3289 }
3290
3291 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
3292 keep_around =
3293 honour_sticky &&
3294 (st.st_uid == 0 || st.st_uid == getuid()) &&
3295 (st.st_mode & S_ISVTX);
ad293f5a 3296 } else {
8c6db833 3297 is_dir = de->d_type == DT_DIR;
7925c22a 3298 keep_around = false;
ad293f5a 3299 }
8c6db833
LP
3300
3301 if (is_dir) {
3302 int subdir_fd;
8c6db833 3303
597f43c7 3304 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
3305 if (root_dev && st.st_dev != root_dev->st_dev)
3306 continue;
8c6db833 3307
7925c22a
LP
3308 subdir_fd = openat(fd, de->d_name,
3309 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3310 if (subdir_fd < 0) {
3311 if (ret == 0 && errno != ENOENT)
3312 ret = -errno;
3313 continue;
3314 }
3315
b3d28469 3316 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
3317 if (r < 0 && ret == 0)
3318 ret = r;
3319
3320 if (!keep_around)
3321 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
3322 if (ret == 0 && errno != ENOENT)
3323 ret = -errno;
3324 }
3325
3326 } else if (!only_dirs && !keep_around) {
8c6db833
LP
3327
3328 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 3329 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3330 ret = -errno;
3331 }
3332 }
3333 }
3334
3335 closedir(d);
3336
3337 return ret;
3338}
3339
f56d5db9
LP
3340int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
3341 struct statfs s;
3342
3343 assert(fd >= 0);
3344
3345 if (fstatfs(fd, &s) < 0) {
3346 close_nointr_nofail(fd);
3347 return -errno;
3348 }
3349
3350 /* We refuse to clean disk file systems with this call. This
3351 * is extra paranoia just to be sure we never ever remove
3352 * non-state data */
3353
3354 if (s.f_type != TMPFS_MAGIC &&
3355 s.f_type != RAMFS_MAGIC) {
3356 log_error("Attempted to remove disk file system, and we can't allow that.");
3357 close_nointr_nofail(fd);
3358 return -EPERM;
3359 }
3360
3361 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
3362}
3363
3364static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
3365 int fd, r;
3366 struct statfs s;
8c6db833
LP
3367
3368 assert(path);
3369
f56d5db9
LP
3370 /* We refuse to clean the root file system with this
3371 * call. This is extra paranoia to never cause a really
3372 * seriously broken system. */
3373 if (path_equal(path, "/")) {
3374 log_error("Attempted to remove entire root file system, and we can't allow that.");
3375 return -EPERM;
3376 }
461b1822 3377
d4d046e3
LP
3378 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3379 if (fd < 0) {
8c6db833
LP
3380
3381 if (errno != ENOTDIR)
3382 return -errno;
3383
f56d5db9
LP
3384 if (!dangerous) {
3385 if (statfs(path, &s) < 0)
3386 return -errno;
3387
3388 if (s.f_type != TMPFS_MAGIC &&
3389 s.f_type != RAMFS_MAGIC) {
3390 log_error("Attempted to remove disk file system, and we can't allow that.");
3391 return -EPERM;
3392 }
3393 }
3394
8c6db833 3395 if (delete_root && !only_dirs)
d4d046e3 3396 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
3397 return -errno;
3398
3399 return 0;
3400 }
3401
f56d5db9
LP
3402 if (!dangerous) {
3403 if (fstatfs(fd, &s) < 0) {
3404 close_nointr_nofail(fd);
3405 return -errno;
3406 }
ad293f5a 3407
f56d5db9
LP
3408 if (s.f_type != TMPFS_MAGIC &&
3409 s.f_type != RAMFS_MAGIC) {
3410 log_error("Attempted to remove disk file system, and we can't allow that.");
3411 close_nointr_nofail(fd);
3412 return -EPERM;
3413 }
3414 }
3415
3416 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
3417 if (delete_root) {
3418
8d53b453 3419 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 3420 return r;
8c6db833 3421
e27796a0 3422 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
3423 if (r == 0)
3424 r = -errno;
3425 }
ad293f5a 3426 }
8c6db833
LP
3427
3428 return r;
3429}
3430
f56d5db9
LP
3431int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3432 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
3433}
3434
3435int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3436 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
3437}
3438
8c6db833
LP
3439int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
3440 assert(path);
3441
3442 /* Under the assumption that we are running privileged we
3443 * first change the access mode and only then hand out
3444 * ownership to avoid a window where access is too open. */
3445
8d53b453
LP
3446 if (mode != (mode_t) -1)
3447 if (chmod(path, mode) < 0)
3448 return -errno;
8c6db833 3449
8d53b453
LP
3450 if (uid != (uid_t) -1 || gid != (gid_t) -1)
3451 if (chown(path, uid, gid) < 0)
3452 return -errno;
8c6db833
LP
3453
3454 return 0;
ef2f1067
LP
3455}
3456
f4b47811
LP
3457int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
3458 assert(fd >= 0);
3459
3460 /* Under the assumption that we are running privileged we
3461 * first change the access mode and only then hand out
3462 * ownership to avoid a window where access is too open. */
3463
3464 if (fchmod(fd, mode) < 0)
3465 return -errno;
3466
3467 if (fchown(fd, uid, gid) < 0)
3468 return -errno;
3469
3470 return 0;
3471}
3472
82c121a4
LP
3473cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
3474 cpu_set_t *r;
3475 unsigned n = 1024;
3476
3477 /* Allocates the cpuset in the right size */
3478
3479 for (;;) {
3480 if (!(r = CPU_ALLOC(n)))
3481 return NULL;
3482
3483 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
3484 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
3485
3486 if (ncpus)
3487 *ncpus = n;
3488
3489 return r;
3490 }
3491
3492 CPU_FREE(r);
3493
3494 if (errno != EINVAL)
3495 return NULL;
3496
3497 n *= 2;
3498 }
3499}
3500
669bec5d 3501int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
9ab7a8d2 3502 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
3503 _cleanup_free_ char *s = NULL;
3504 _cleanup_close_ int fd = -1;
81beb750
LP
3505 struct iovec iovec[5];
3506 int n = 0;
9e58ff9c
LP
3507
3508 assert(format);
3509
9ab7a8d2 3510 /* This is independent of logging, as status messages are
9e58ff9c
LP
3511 * optional and go exclusively to the console. */
3512
3513 if (vasprintf(&s, format, ap) < 0)
669bec5d 3514 return log_oom();
9e58ff9c 3515
67e5cc4f 3516 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 3517 if (fd < 0)
669bec5d 3518 return fd;
9e58ff9c 3519
67e5cc4f 3520 if (ellipse) {
9ab7a8d2
MS
3521 char *e;
3522 size_t emax, sl;
3523 int c;
3524
67e5cc4f
LP
3525 c = fd_columns(fd);
3526 if (c <= 0)
3527 c = 80;
81beb750 3528
669bec5d 3529 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
3530
3531 emax = c - sl - 1;
3532 if (emax < 3)
3533 emax = 3;
81beb750 3534
67e5cc4f
LP
3535 e = ellipsize(s, emax, 75);
3536 if (e) {
3537 free(s);
3538 s = e;
3539 }
81beb750
LP
3540 }
3541
3542 zero(iovec);
81beb750 3543
9ab7a8d2
MS
3544 if (status) {
3545 if (!isempty(status)) {
3546 IOVEC_SET_STRING(iovec[n++], "[");
3547 IOVEC_SET_STRING(iovec[n++], status);
3548 IOVEC_SET_STRING(iovec[n++], "] ");
3549 } else
3550 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
3551 }
3552
9ab7a8d2
MS
3553 IOVEC_SET_STRING(iovec[n++], s);
3554 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 3555
669bec5d
LP
3556 if (writev(fd, iovec, n) < 0)
3557 return -errno;
9e58ff9c 3558
669bec5d 3559 return 0;
9e58ff9c
LP
3560}
3561
669bec5d 3562int status_printf(const char *status, bool ellipse, const char *format, ...) {
c846ff47 3563 va_list ap;
669bec5d 3564 int r;
c846ff47
LP
3565
3566 assert(format);
3567
3568 va_start(ap, format);
669bec5d 3569 r = status_vprintf(status, ellipse, format, ap);
c846ff47 3570 va_end(ap);
669bec5d
LP
3571
3572 return r;
c846ff47
LP
3573}
3574
669bec5d 3575int status_welcome(void) {
10aa7034 3576 int r;
669bec5d
LP
3577 _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
3578
3579 r = parse_env_file("/etc/os-release", NEWLINE,
3580 "PRETTY_NAME", &pretty_name,
3581 "ANSI_COLOR", &ansi_color,
3582 NULL);
3583 if (r < 0 && r != -ENOENT)
3584 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3585
3586 return status_printf(NULL, false,
3587 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3588 isempty(ansi_color) ? "1" : ansi_color,
3589 isempty(pretty_name) ? "Linux" : pretty_name);
c846ff47
LP
3590}
3591
fab56fc5
LP
3592char *replace_env(const char *format, char **env) {
3593 enum {
3594 WORD,
c24eb49e 3595 CURLY,
fab56fc5
LP
3596 VARIABLE
3597 } state = WORD;
3598
3599 const char *e, *word = format;
3600 char *r = NULL, *k;
3601
3602 assert(format);
3603
3604 for (e = format; *e; e ++) {
3605
3606 switch (state) {
3607
3608 case WORD:
3609 if (*e == '$')
c24eb49e 3610 state = CURLY;
fab56fc5
LP
3611 break;
3612
c24eb49e
LP
3613 case CURLY:
3614 if (*e == '{') {
fab56fc5
LP
3615 if (!(k = strnappend(r, word, e-word-1)))
3616 goto fail;
3617
3618 free(r);
3619 r = k;
3620
3621 word = e-1;
3622 state = VARIABLE;
3623
3624 } else if (*e == '$') {
3625 if (!(k = strnappend(r, word, e-word)))
3626 goto fail;
3627
3628 free(r);
3629 r = k;
3630
3631 word = e+1;
3632 state = WORD;
3633 } else
3634 state = WORD;
3635 break;
3636
3637 case VARIABLE:
c24eb49e 3638 if (*e == '}') {
b95cf362 3639 const char *t;
fab56fc5 3640
b95cf362
LP
3641 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
3642 t = "";
fab56fc5 3643
b95cf362
LP
3644 if (!(k = strappend(r, t)))
3645 goto fail;
fab56fc5 3646
b95cf362
LP
3647 free(r);
3648 r = k;
fab56fc5 3649
b95cf362 3650 word = e+1;
fab56fc5
LP
3651 state = WORD;
3652 }
3653 break;
3654 }
3655 }
3656
3657 if (!(k = strnappend(r, word, e-word)))
3658 goto fail;
3659
3660 free(r);
3661 return k;
3662
3663fail:
3664 free(r);
3665 return NULL;
3666}
3667
3668char **replace_env_argv(char **argv, char **env) {
3669 char **r, **i;
c24eb49e
LP
3670 unsigned k = 0, l = 0;
3671
3672 l = strv_length(argv);
fab56fc5 3673
c24eb49e 3674 if (!(r = new(char*, l+1)))
fab56fc5
LP
3675 return NULL;
3676
3677 STRV_FOREACH(i, argv) {
c24eb49e
LP
3678
3679 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3680 if ((*i)[0] == '$' && (*i)[1] != '{') {
3681 char *e;
3682 char **w, **m;
3683 unsigned q;
c24eb49e 3684
b95cf362 3685 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
3686
3687 if (!(m = strv_split_quoted(e))) {
3688 r[k] = NULL;
3689 strv_free(r);
3690 return NULL;
3691 }
b95cf362
LP
3692 } else
3693 m = NULL;
c24eb49e 3694
b95cf362
LP
3695 q = strv_length(m);
3696 l = l + q - 1;
c24eb49e 3697
b95cf362
LP
3698 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3699 r[k] = NULL;
3700 strv_free(r);
3701 strv_free(m);
3702 return NULL;
3703 }
c24eb49e 3704
b95cf362
LP
3705 r = w;
3706 if (m) {
c24eb49e
LP
3707 memcpy(r + k, m, q * sizeof(char*));
3708 free(m);
c24eb49e 3709 }
b95cf362
LP
3710
3711 k += q;
3712 continue;
c24eb49e
LP
3713 }
3714
3715 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3716 if (!(r[k++] = replace_env(*i, env))) {
3717 strv_free(r);
3718 return NULL;
3719 }
3720 }
3721
3722 r[k] = NULL;
3723 return r;
3724}
3725
81beb750
LP
3726int fd_columns(int fd) {
3727 struct winsize ws;
3728 zero(ws);
3729
3730 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3731 return -errno;
3732
3733 if (ws.ws_col <= 0)
3734 return -EIO;
3735
3736 return ws.ws_col;
3737}
3738
11f96fac
ZJS
3739static unsigned columns_cached(bool cached) {
3740 static __thread int parsed_columns = 0, env_columns = -1;
fa776d8e
LP
3741 const char *e;
3742
11f96fac 3743 if (_likely_(parsed_columns > 0 && cached))
fa776d8e
LP
3744 return parsed_columns;
3745
11f96fac
ZJS
3746 if (_unlikely_(env_columns == -1)) {
3747 e = getenv("COLUMNS");
3748 if (e)
3749 env_columns = atoi(e);
3750 else
3751 env_columns = 0;
3752 }
fa776d8e 3753
11f96fac
ZJS
3754 if (env_columns > 0) {
3755 parsed_columns = env_columns;
3756 return parsed_columns;
3757 }
3758
3759 if (parsed_columns <= 0 || !cached)
81beb750 3760 parsed_columns = fd_columns(STDOUT_FILENO);
fa776d8e
LP
3761
3762 if (parsed_columns <= 0)
3763 parsed_columns = 80;
3764
3765 return parsed_columns;
3766}
3767
11f96fac
ZJS
3768unsigned columns(void) {
3769 return columns_cached(true);
3770}
3771
3772unsigned columns_uncached(void) {
3773 return columns_cached(false);
3774}
3775
8f2d43a0
LP
3776int fd_lines(int fd) {
3777 struct winsize ws;
3778 zero(ws);
3779
3780 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3781 return -errno;
3782
3783 if (ws.ws_row <= 0)
3784 return -EIO;
3785
3786 return ws.ws_row;
3787}
3788
3789unsigned lines(void) {
3790 static __thread int parsed_lines = 0;
3791 const char *e;
3792
3793 if (_likely_(parsed_lines > 0))
3794 return parsed_lines;
3795
3796 e = getenv("LINES");
3797 if (e)
3798 parsed_lines = atoi(e);
3799
3800 if (parsed_lines <= 0)
3801 parsed_lines = fd_lines(STDOUT_FILENO);
3802
3803 if (parsed_lines <= 0)
3804 parsed_lines = 25;
3805
3806 return parsed_lines;
3807}
3808
b4f10a5e
LP
3809int running_in_chroot(void) {
3810 struct stat a, b;
3811
3812 zero(a);
3813 zero(b);
3814
3815 /* Only works as root */
3816
3817 if (stat("/proc/1/root", &a) < 0)
3818 return -errno;
3819
3820 if (stat("/", &b) < 0)
3821 return -errno;
3822
3823 return
3824 a.st_dev != b.st_dev ||
3825 a.st_ino != b.st_ino;
3826}
3827
72f59706
LP
3828char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3829 size_t x;
8fe914ec
LP
3830 char *r;
3831
3832 assert(s);
3833 assert(percent <= 100);
72f59706 3834 assert(new_length >= 3);
8fe914ec 3835
72f59706
LP
3836 if (old_length <= 3 || old_length <= new_length)
3837 return strndup(s, old_length);
8fe914ec 3838
72f59706
LP
3839 r = new0(char, new_length+1);
3840 if (!r)
8fe914ec
LP
3841 return r;
3842
72f59706 3843 x = (new_length * percent) / 100;
8fe914ec 3844
72f59706
LP
3845 if (x > new_length - 3)
3846 x = new_length - 3;
8fe914ec
LP
3847
3848 memcpy(r, s, x);
3849 r[x] = '.';
3850 r[x+1] = '.';
3851 r[x+2] = '.';
3852 memcpy(r + x + 3,
72f59706
LP
3853 s + old_length - (new_length - x - 3),
3854 new_length - x - 3);
8fe914ec
LP
3855
3856 return r;
3857}
3858
72f59706
LP
3859char *ellipsize(const char *s, size_t length, unsigned percent) {
3860 return ellipsize_mem(s, strlen(s), length, percent);
3861}
3862
f6144808
LP
3863int touch(const char *path) {
3864 int fd;
3865
3866 assert(path);
3867
73836c5c
LP
3868 /* This just opens the file for writing, ensuring it
3869 * exists. It doesn't call utimensat() the way /usr/bin/touch
3870 * does it. */
3871
3872 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3873 if (fd < 0)
f6144808
LP
3874 return -errno;
3875
3876 close_nointr_nofail(fd);
3877 return 0;
3878}
afea26ad 3879
97c4a07d 3880char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3881 size_t l;
3882 assert(s);
3883
73836c5c
LP
3884 /* This is rather stupid, simply removes the heading and
3885 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3886 * escaping or anything. We should make this smarter one
3887 * day...*/
73836c5c 3888
31ed59c5
LP
3889 l = strlen(s);
3890 if (l < 2)
11ce3427
LP
3891 return strdup(s);
3892
97c4a07d 3893 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3894 return strndup(s+1, l-2);
3895
3896 return strdup(s);
3897}
3898
5f7c426e 3899char *normalize_env_assignment(const char *s) {
57f30678
LP
3900 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3901 char *eq, *r;
5f7c426e 3902
57f30678
LP
3903 eq = strchr(s, '=');
3904 if (!eq) {
3905 char *t;
5f7c426e 3906
57f30678
LP
3907 r = strdup(s);
3908 if (!r)
5f7c426e
LP
3909 return NULL;
3910
57f30678
LP
3911 t = strstrip(r);
3912 if (t == r)
3913 return r;
3914
3915 memmove(r, t, strlen(t) + 1);
3916 return r;
5f7c426e
LP
3917 }
3918
57f30678
LP
3919 name = strndup(s, eq - s);
3920 if (!name)
5f7c426e
LP
3921 return NULL;
3922
57f30678
LP
3923 p = strdup(eq + 1);
3924 if (!p)
5f7c426e 3925 return NULL;
5f7c426e
LP
3926
3927 value = unquote(strstrip(p), QUOTES);
57f30678 3928 if (!value)
5f7c426e 3929 return NULL;
5f7c426e 3930
57f30678 3931 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3932 r = NULL;
3933
5f7c426e
LP
3934 return r;
3935}
3936
8e12a6ae 3937int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3938 siginfo_t dummy;
3939
2e78aa99 3940 assert(pid >= 1);
1968a360
LP
3941
3942 if (!status)
3943 status = &dummy;
2e78aa99
LP
3944
3945 for (;;) {
8e12a6ae
LP
3946 zero(*status);
3947
3948 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3949
3950 if (errno == EINTR)
3951 continue;
3952
3953 return -errno;
3954 }
3955
3956 return 0;
3957 }
3958}
3959
97c4a07d
LP
3960int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3961 int r;
3962 siginfo_t status;
3963
3964 assert(name);
3965 assert(pid > 1);
3966
d87be9b0
LP
3967 r = wait_for_terminate(pid, &status);
3968 if (r < 0) {
97c4a07d
LP
3969 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3970 return r;
3971 }
3972
3973 if (status.si_code == CLD_EXITED) {
3974 if (status.si_status != 0) {
3975 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3976 return status.si_status;
97c4a07d
LP
3977 }
3978
3979 log_debug("%s succeeded.", name);
3980 return 0;
3981
3982 } else if (status.si_code == CLD_KILLED ||
3983 status.si_code == CLD_DUMPED) {
3984
3985 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3986 return -EPROTO;
3987 }
3988
3989 log_warning("%s failed due to unknown reason.", name);
3990 return -EPROTO;
97c4a07d
LP
3991}
3992
6a39419f 3993_noreturn_ void freeze(void) {
720ce21d
LP
3994
3995 /* Make sure nobody waits for us on a socket anymore */
3996 close_all_fds(NULL, 0);
3997
c29597a1
LP
3998 sync();
3999
3c14d26c
LP
4000 for (;;)
4001 pause();
4002}
4003
00dc5d76
LP
4004bool null_or_empty(struct stat *st) {
4005 assert(st);
4006
4007 if (S_ISREG(st->st_mode) && st->st_size <= 0)
4008 return true;
4009
c8f26f42 4010 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
4011 return true;
4012
4013 return false;
4014}
4015
83096483
LP
4016int null_or_empty_path(const char *fn) {
4017 struct stat st;
4018
4019 assert(fn);
4020
4021 if (stat(fn, &st) < 0)
4022 return -errno;
4023
4024 return null_or_empty(&st);
4025}
4026
a247755d 4027DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
4028 int nfd;
4029 DIR *d;
4030
73836c5c
LP
4031 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
4032 if (nfd < 0)
c4731d11
LP
4033 return NULL;
4034
73836c5c
LP
4035 d = fdopendir(nfd);
4036 if (!d) {
c4731d11
LP
4037 close_nointr_nofail(nfd);
4038 return NULL;
4039 }
4040
4041 return d;
3b63d2d3
LP
4042}
4043
8a0867d6
LP
4044int signal_from_string_try_harder(const char *s) {
4045 int signo;
4046 assert(s);
4047
73836c5c
LP
4048 signo = signal_from_string(s);
4049 if (signo <= 0)
8a0867d6
LP
4050 if (startswith(s, "SIG"))
4051 return signal_from_string(s+3);
4052
4053 return signo;
4054}
4055
10717a1a
LP
4056void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
4057
4058 assert(f);
4059 assert(name);
4060 assert(t);
4061
4062 if (!dual_timestamp_is_set(t))
4063 return;
4064
4065 fprintf(f, "%s=%llu %llu\n",
4066 name,
4067 (unsigned long long) t->realtime,
4068 (unsigned long long) t->monotonic);
4069}
4070
799fd0fd 4071void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
10717a1a
LP
4072 unsigned long long a, b;
4073
10717a1a
LP
4074 assert(value);
4075 assert(t);
4076
4077 if (sscanf(value, "%lli %llu", &a, &b) != 2)
4078 log_debug("Failed to parse finish timestamp value %s", value);
4079 else {
4080 t->realtime = a;
4081 t->monotonic = b;
4082 }
4083}
4084
383182b5 4085static char *tag_to_udev_node(const char *tagvalue, const char *by) {
e23a0ce8
LP
4086 char *dn, *t, *u;
4087 int r;
4088
4089 /* FIXME: to follow udev's logic 100% we need to leave valid
4090 * UTF8 chars unescaped */
4091
383182b5
DR
4092 u = unquote(tagvalue, "\"\'");
4093 if (u == NULL)
4094 return NULL;
e23a0ce8 4095
383182b5
DR
4096 t = xescape(u, "/ ");
4097 free(u);
e23a0ce8 4098
383182b5
DR
4099 if (t == NULL)
4100 return NULL;
e23a0ce8 4101
383182b5
DR
4102 r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
4103 free(t);
e23a0ce8 4104
383182b5
DR
4105 if (r < 0)
4106 return NULL;
e23a0ce8 4107
383182b5
DR
4108 return dn;
4109}
e23a0ce8 4110
383182b5 4111char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
4112 assert(p);
4113
383182b5
DR
4114 if (startswith(p, "LABEL="))
4115 return tag_to_udev_node(p+6, "label");
e23a0ce8 4116
383182b5
DR
4117 if (startswith(p, "UUID="))
4118 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 4119
84cc2abf
DR
4120 if (startswith(p, "PARTUUID="))
4121 return tag_to_udev_node(p+9, "partuuid");
4122
4123 if (startswith(p, "PARTLABEL="))
4124 return tag_to_udev_node(p+10, "partlabel");
4125
e23a0ce8
LP
4126 return strdup(p);
4127}
4128
f212ac12
LP
4129bool tty_is_vc(const char *tty) {
4130 assert(tty);
4131
4132 if (startswith(tty, "/dev/"))
4133 tty += 5;
4134
98a28fef
LP
4135 return vtnr_from_tty(tty) >= 0;
4136}
4137
d1122ad5
LP
4138bool tty_is_console(const char *tty) {
4139 assert(tty);
4140
4141 if (startswith(tty, "/dev/"))
4142 tty += 5;
4143
4144 return streq(tty, "console");
4145}
4146
98a28fef
LP
4147int vtnr_from_tty(const char *tty) {
4148 int i, r;
4149
4150 assert(tty);
4151
4152 if (startswith(tty, "/dev/"))
4153 tty += 5;
4154
4155 if (!startswith(tty, "tty") )
4156 return -EINVAL;
4157
4158 if (tty[3] < '0' || tty[3] > '9')
4159 return -EINVAL;
4160
4161 r = safe_atoi(tty+3, &i);
4162 if (r < 0)
4163 return r;
4164
4165 if (i < 0 || i > 63)
4166 return -EINVAL;
4167
4168 return i;
f212ac12
LP
4169}
4170
3043935f 4171bool tty_is_vc_resolve(const char *tty) {
3030ccd7 4172 char *active = NULL;
3043935f 4173 bool b;
3030ccd7 4174
e3aa71c3
LP
4175 assert(tty);
4176
4177 if (startswith(tty, "/dev/"))
4178 tty += 5;
4179
3d9a4122
LP
4180 /* Resolve where /dev/console is pointing to, if /sys is
4181 * actually ours (i.e. not read-only-mounted which is a sign
4182 * for container setups) */
4183 if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
3030ccd7 4184 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4185 /* If multiple log outputs are configured the
4186 * last one is what /dev/console points to */
3043935f
LP
4187 tty = strrchr(active, ' ');
4188 if (tty)
079a09fb
LP
4189 tty++;
4190 else
4191 tty = active;
3030ccd7
LP
4192 }
4193
3043935f 4194 b = tty_is_vc(tty);
3030ccd7 4195 free(active);
e3aa71c3 4196
3043935f
LP
4197 return b;
4198}
4199
4200const char *default_term_for_tty(const char *tty) {
4201 assert(tty);
4202
acda6a05 4203 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
4204}
4205
87d2c1ff 4206bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4207 assert(de);
4208
4209 if (ignore_file(de->d_name))
4210 return false;
4211
4212 if (de->d_type != DT_REG &&
4213 de->d_type != DT_LNK &&
4214 de->d_type != DT_UNKNOWN)
4215 return false;
4216
4217 return true;
4218}
4219
87d2c1ff
LP
4220bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4221 assert(de);
4222
a228a22f
LP
4223 if (de->d_type != DT_REG &&
4224 de->d_type != DT_LNK &&
4225 de->d_type != DT_UNKNOWN)
4226 return false;
4227
4228 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
4229 return false;
4230
4231 return endswith(de->d_name, suffix);
4232}
4233
83cc030f
LP
4234void execute_directory(const char *directory, DIR *d, char *argv[]) {
4235 DIR *_d = NULL;
4236 struct dirent *de;
4237 Hashmap *pids = NULL;
4238
4239 assert(directory);
4240
4241 /* Executes all binaries in a directory in parallel and waits
4242 * until all they all finished. */
4243
4244 if (!d) {
4245 if (!(_d = opendir(directory))) {
4246
4247 if (errno == ENOENT)
4248 return;
4249
4250 log_error("Failed to enumerate directory %s: %m", directory);
4251 return;
4252 }
4253
4254 d = _d;
4255 }
4256
4257 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4258 log_error("Failed to allocate set.");
4259 goto finish;
4260 }
4261
4262 while ((de = readdir(d))) {
4263 char *path;
4264 pid_t pid;
4265 int k;
4266
fb19a739 4267 if (!dirent_is_file(de))
83cc030f
LP
4268 continue;
4269
4270 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 4271 log_oom();
83cc030f
LP
4272 continue;
4273 }
4274
4275 if ((pid = fork()) < 0) {
4276 log_error("Failed to fork: %m");
4277 free(path);
4278 continue;
4279 }
4280
4281 if (pid == 0) {
4282 char *_argv[2];
4283 /* Child */
4284
4285 if (!argv) {
4286 _argv[0] = path;
4287 _argv[1] = NULL;
4288 argv = _argv;
4289 } else
6edd7d0a 4290 argv[0] = path;
83cc030f
LP
4291
4292 execv(path, argv);
4293
4294 log_error("Failed to execute %s: %m", path);
4295 _exit(EXIT_FAILURE);
4296 }
4297
4298 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4299
4300 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4301 log_error("Failed to add PID to set: %s", strerror(-k));
4302 free(path);
4303 }
4304 }
4305
4306 while (!hashmap_isempty(pids)) {
ec3f9b53 4307 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
4308 siginfo_t si;
4309 char *path;
4310
4311 zero(si);
ec3f9b53 4312 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
4313
4314 if (errno == EINTR)
4315 continue;
4316
4317 log_error("waitid() failed: %m");
4318 goto finish;
4319 }
4320
4321 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 4322 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
4323 if (si.si_code == CLD_EXITED)
4324 log_error("%s exited with exit status %i.", path, si.si_status);
4325 else
4326 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4327 } else
4328 log_debug("%s exited successfully.", path);
4329
4330 free(path);
4331 }
4332 }
4333
4334finish:
4335 if (_d)
4336 closedir(_d);
4337
4338 if (pids)
4339 hashmap_free_free(pids);
4340}
4341
430c18ed
LP
4342int kill_and_sigcont(pid_t pid, int sig) {
4343 int r;
4344
4345 r = kill(pid, sig) < 0 ? -errno : 0;
4346
4347 if (r >= 0)
4348 kill(pid, SIGCONT);
4349
4350 return r;
4351}
4352
05feefe0
LP
4353bool nulstr_contains(const char*nulstr, const char *needle) {
4354 const char *i;
4355
4356 if (!nulstr)
4357 return false;
4358
4359 NULSTR_FOREACH(i, nulstr)
4360 if (streq(i, needle))
4361 return true;
4362
4363 return false;
4364}
4365
6faa1114 4366bool plymouth_running(void) {
9408a2d2 4367 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4368}
4369
9beb3f4d
LP
4370char* strshorten(char *s, size_t l) {
4371 assert(s);
4372
4373 if (l < strlen(s))
4374 s[l] = 0;
4375
4376 return s;
4377}
4378
4379static bool hostname_valid_char(char c) {
4380 return
4381 (c >= 'a' && c <= 'z') ||
4382 (c >= 'A' && c <= 'Z') ||
4383 (c >= '0' && c <= '9') ||
4384 c == '-' ||
4385 c == '_' ||
4386 c == '.';
4387}
4388
4389bool hostname_is_valid(const char *s) {
4390 const char *p;
4391
4392 if (isempty(s))
4393 return false;
4394
4395 for (p = s; *p; p++)
4396 if (!hostname_valid_char(*p))
4397 return false;
4398
4399 if (p-s > HOST_NAME_MAX)
4400 return false;
4401
4402 return true;
4403}
4404
4405char* hostname_cleanup(char *s) {
4406 char *p, *d;
4407
4408 for (p = s, d = s; *p; p++)
4409 if ((*p >= 'a' && *p <= 'z') ||
4410 (*p >= 'A' && *p <= 'Z') ||
4411 (*p >= '0' && *p <= '9') ||
4412 *p == '-' ||
4413 *p == '_' ||
4414 *p == '.')
4415 *(d++) = *p;
4416
4417 *d = 0;
4418
4419 strshorten(s, HOST_NAME_MAX);
4420 return s;
4421}
4422
1325aa42
LP
4423int pipe_eof(int fd) {
4424 struct pollfd pollfd;
4425 int r;
4426
4427 zero(pollfd);
4428 pollfd.fd = fd;
4429 pollfd.events = POLLIN|POLLHUP;
4430
4431 r = poll(&pollfd, 1, 0);
4432 if (r < 0)
4433 return -errno;
4434
4435 if (r == 0)
4436 return 0;
4437
4438 return pollfd.revents & POLLHUP;
4439}
4440
8f2d43a0 4441int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
4442 struct pollfd pollfd;
4443 int r;
4444
4445 zero(pollfd);
4446 pollfd.fd = fd;
4447 pollfd.events = event;
4448
8f2d43a0 4449 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
4450 if (r < 0)
4451 return -errno;
4452
4453 if (r == 0)
4454 return 0;
4455
4456 return pollfd.revents;
4457}
4458
5a3ab509
LP
4459int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4460 FILE *f;
4461 char *t;
4462 const char *fn;
4463 size_t k;
4464 int fd;
4465
4466 assert(path);
4467 assert(_f);
4468 assert(_temp_path);
4469
4470 t = new(char, strlen(path) + 1 + 6 + 1);
4471 if (!t)
4472 return -ENOMEM;
4473
9eb977db 4474 fn = path_get_file_name(path);
5a3ab509
LP
4475 k = fn-path;
4476 memcpy(t, path, k);
4477 t[k] = '.';
4478 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4479
4480 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4481 if (fd < 0) {
4482 free(t);
4483 return -errno;
4484 }
4485
4486 f = fdopen(fd, "we");
4487 if (!f) {
4488 unlink(t);
4489 free(t);
4490 return -errno;
4491 }
4492
4493 *_f = f;
4494 *_temp_path = t;
4495
4496 return 0;
4497}
4498
6ea832a2 4499int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4500 assert(fd >= 0);
4501
6ea832a2
LP
4502 if (ioctl(fd, TIOCVHANGUP) < 0)
4503 return -errno;
4504
4505 return 0;
4506}
4507
4508int terminal_vhangup(const char *name) {
4509 int fd, r;
4510
4511 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4512 if (fd < 0)
4513 return fd;
4514
4515 r = terminal_vhangup_fd(fd);
4516 close_nointr_nofail(fd);
4517
4518 return r;
4519}
4520
4521int vt_disallocate(const char *name) {
4522 int fd, r;
4523 unsigned u;
6ea832a2
LP
4524
4525 /* Deallocate the VT if possible. If not possible
4526 * (i.e. because it is the active one), at least clear it
4527 * entirely (including the scrollback buffer) */
4528
b83bc4e9
LP
4529 if (!startswith(name, "/dev/"))
4530 return -EINVAL;
4531
4532 if (!tty_is_vc(name)) {
4533 /* So this is not a VT. I guess we cannot deallocate
4534 * it then. But let's at least clear the screen */
4535
4536 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4537 if (fd < 0)
4538 return fd;
4539
8585357a
LP
4540 loop_write(fd,
4541 "\033[r" /* clear scrolling region */
4542 "\033[H" /* move home */
4543 "\033[2J", /* clear screen */
4544 10, false);
b83bc4e9
LP
4545 close_nointr_nofail(fd);
4546
4547 return 0;
4548 }
6ea832a2
LP
4549
4550 if (!startswith(name, "/dev/tty"))
4551 return -EINVAL;
4552
4553 r = safe_atou(name+8, &u);
4554 if (r < 0)
4555 return r;
4556
4557 if (u <= 0)
b83bc4e9 4558 return -EINVAL;
6ea832a2 4559
b83bc4e9 4560 /* Try to deallocate */
6ea832a2
LP
4561 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4562 if (fd < 0)
4563 return fd;
4564
4565 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4566 close_nointr_nofail(fd);
6ea832a2 4567
b83bc4e9
LP
4568 if (r >= 0)
4569 return 0;
6ea832a2 4570
b83bc4e9 4571 if (errno != EBUSY)
6ea832a2 4572 return -errno;
6ea832a2 4573
b83bc4e9
LP
4574 /* Couldn't deallocate, so let's clear it fully with
4575 * scrollback */
4576 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4577 if (fd < 0)
b83bc4e9 4578 return fd;
6ea832a2 4579
8585357a
LP
4580 loop_write(fd,
4581 "\033[r" /* clear scrolling region */
4582 "\033[H" /* move home */
4583 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4584 10, false);
b83bc4e9 4585 close_nointr_nofail(fd);
6ea832a2 4586
b83bc4e9 4587 return 0;
6ea832a2
LP
4588}
4589
34ca941c
LP
4590int copy_file(const char *from, const char *to) {
4591 int r, fdf, fdt;
4592
4593 assert(from);
4594 assert(to);
4595
4596 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4597 if (fdf < 0)
4598 return -errno;
4599
4600 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4601 if (fdt < 0) {
4602 close_nointr_nofail(fdf);
4603 return -errno;
4604 }
4605
4606 for (;;) {
4607 char buf[PIPE_BUF];
4608 ssize_t n, k;
4609
4610 n = read(fdf, buf, sizeof(buf));
4611 if (n < 0) {
4612 r = -errno;
4613
4614 close_nointr_nofail(fdf);
4615 close_nointr(fdt);
4616 unlink(to);
4617
4618 return r;
4619 }
4620
4621 if (n == 0)
4622 break;
4623
4624 errno = 0;
4625 k = loop_write(fdt, buf, n, false);
4626 if (n != k) {
4627 r = k < 0 ? k : (errno ? -errno : -EIO);
4628
4629 close_nointr_nofail(fdf);
4630 close_nointr(fdt);
4631
4632 unlink(to);
4633 return r;
4634 }
4635 }
4636
4637 close_nointr_nofail(fdf);
4638 r = close_nointr(fdt);
4639
4640 if (r < 0) {
4641 unlink(to);
4642 return r;
4643 }
4644
4645 return 0;
4646}
4647
424a19f8
LP
4648int symlink_atomic(const char *from, const char *to) {
4649 char *x;
4650 _cleanup_free_ char *t;
34ca941c
LP
4651 const char *fn;
4652 size_t k;
4653 unsigned long long ull;
4654 unsigned i;
4655 int r;
4656
4657 assert(from);
4658 assert(to);
4659
4660 t = new(char, strlen(to) + 1 + 16 + 1);
4661 if (!t)
4662 return -ENOMEM;
4663
9eb977db 4664 fn = path_get_file_name(to);
34ca941c
LP
4665 k = fn-to;
4666 memcpy(t, to, k);
4667 t[k] = '.';
4668 x = stpcpy(t+k+1, fn);
4669
4670 ull = random_ull();
4671 for (i = 0; i < 16; i++) {
4672 *(x++) = hexchar(ull & 0xF);
4673 ull >>= 4;
4674 }
4675
4676 *x = 0;
4677
424a19f8
LP
4678 if (symlink(from, t) < 0)
4679 return -errno;
34ca941c
LP
4680
4681 if (rename(t, to) < 0) {
4682 r = -errno;
4683 unlink(t);
34ca941c
LP
4684 return r;
4685 }
4686
424a19f8 4687 return 0;
34ca941c
LP
4688}
4689
4d6d6518
LP
4690bool display_is_local(const char *display) {
4691 assert(display);
4692
4693 return
4694 display[0] == ':' &&
4695 display[1] >= '0' &&
4696 display[1] <= '9';
4697}
4698
4699int socket_from_display(const char *display, char **path) {
4700 size_t k;
4701 char *f, *c;
4702
4703 assert(display);
4704 assert(path);
4705
4706 if (!display_is_local(display))
4707 return -EINVAL;
4708
4709 k = strspn(display+1, "0123456789");
4710
4711 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4712 if (!f)
4713 return -ENOMEM;
4714
4715 c = stpcpy(f, "/tmp/.X11-unix/X");
4716 memcpy(c, display+1, k);
4717 c[k] = 0;
4718
4719 *path = f;
4720
4721 return 0;
4722}
4723
d05c5031
LP
4724int get_user_creds(
4725 const char **username,
4726 uid_t *uid, gid_t *gid,
4727 const char **home,
4728 const char **shell) {
4729
1cccf435 4730 struct passwd *p;
ddd88763 4731 uid_t u;
1cccf435
MV
4732
4733 assert(username);
4734 assert(*username);
1cccf435
MV
4735
4736 /* We enforce some special rules for uid=0: in order to avoid
4737 * NSS lookups for root we hardcode its data. */
4738
4739 if (streq(*username, "root") || streq(*username, "0")) {
4740 *username = "root";
4b67834e
LP
4741
4742 if (uid)
4743 *uid = 0;
4744
4745 if (gid)
4746 *gid = 0;
4747
4748 if (home)
4749 *home = "/root";
d05c5031
LP
4750
4751 if (shell)
4752 *shell = "/bin/sh";
4753
1cccf435
MV
4754 return 0;
4755 }
4756
ddd88763 4757 if (parse_uid(*username, &u) >= 0) {
1cccf435 4758 errno = 0;
ddd88763 4759 p = getpwuid(u);
1cccf435
MV
4760
4761 /* If there are multiple users with the same id, make
4762 * sure to leave $USER to the configured value instead
4763 * of the first occurrence in the database. However if
4764 * the uid was configured by a numeric uid, then let's
4765 * pick the real username from /etc/passwd. */
4766 if (p)
4767 *username = p->pw_name;
4768 } else {
4769 errno = 0;
4770 p = getpwnam(*username);
4771 }
4772
4773 if (!p)
4774 return errno != 0 ? -errno : -ESRCH;
4775
4b67834e
LP
4776 if (uid)
4777 *uid = p->pw_uid;
4778
4779 if (gid)
4780 *gid = p->pw_gid;
4781
4782 if (home)
4783 *home = p->pw_dir;
4784
d05c5031
LP
4785 if (shell)
4786 *shell = p->pw_shell;
4787
4b67834e
LP
4788 return 0;
4789}
4790
4791int get_group_creds(const char **groupname, gid_t *gid) {
4792 struct group *g;
4793 gid_t id;
4794
4795 assert(groupname);
4796
4797 /* We enforce some special rules for gid=0: in order to avoid
4798 * NSS lookups for root we hardcode its data. */
4799
4800 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4801 *groupname = "root";
4802
4803 if (gid)
4804 *gid = 0;
4805
4806 return 0;
4807 }
4808
4809 if (parse_gid(*groupname, &id) >= 0) {
4810 errno = 0;
4811 g = getgrgid(id);
4812
4813 if (g)
4814 *groupname = g->gr_name;
4815 } else {
4816 errno = 0;
4817 g = getgrnam(*groupname);
4818 }
4819
4820 if (!g)
4821 return errno != 0 ? -errno : -ESRCH;
4822
4823 if (gid)
4824 *gid = g->gr_gid;
4825
1cccf435
MV
4826 return 0;
4827}
4828
43673799
LP
4829int in_group(const char *name) {
4830 gid_t gid, *gids;
4831 int ngroups_max, r, i;
4832
4833 r = get_group_creds(&name, &gid);
4834 if (r < 0)
4835 return r;
4836
4837 if (getgid() == gid)
4838 return 1;
4839
4840 if (getegid() == gid)
4841 return 1;
4842
4843 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4844 assert(ngroups_max > 0);
4845
4846 gids = alloca(sizeof(gid_t) * ngroups_max);
4847
4848 r = getgroups(ngroups_max, gids);
4849 if (r < 0)
4850 return -errno;
4851
4852 for (i = 0; i < r; i++)
4853 if (gids[i] == gid)
4854 return 1;
4855
4856 return 0;
4857}
4858
8092a428
LP
4859int glob_exists(const char *path) {
4860 glob_t g;
4861 int r, k;
4862
4863 assert(path);
4864
4865 zero(g);
4866 errno = 0;
4867 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4868
4869 if (k == GLOB_NOMATCH)
4870 r = 0;
4871 else if (k == GLOB_NOSPACE)
4872 r = -ENOMEM;
4873 else if (k == 0)
4874 r = !strv_isempty(g.gl_pathv);
4875 else
4876 r = errno ? -errno : -EIO;
4877
4878 globfree(&g);
4879
4880 return r;
4881}
4882
83096483
LP
4883int dirent_ensure_type(DIR *d, struct dirent *de) {
4884 struct stat st;
4885
4886 assert(d);
4887 assert(de);
4888
4889 if (de->d_type != DT_UNKNOWN)
4890 return 0;
4891
4892 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4893 return -errno;
4894
4895 de->d_type =
4896 S_ISREG(st.st_mode) ? DT_REG :
4897 S_ISDIR(st.st_mode) ? DT_DIR :
4898 S_ISLNK(st.st_mode) ? DT_LNK :
4899 S_ISFIFO(st.st_mode) ? DT_FIFO :
4900 S_ISSOCK(st.st_mode) ? DT_SOCK :
4901 S_ISCHR(st.st_mode) ? DT_CHR :
4902 S_ISBLK(st.st_mode) ? DT_BLK :
4903 DT_UNKNOWN;
4904
4905 return 0;
4906}
4907
4908int in_search_path(const char *path, char **search) {
4909 char **i, *parent;
4910 int r;
4911
9eb977db 4912 r = path_get_parent(path, &parent);
83096483
LP
4913 if (r < 0)
4914 return r;
4915
4916 r = 0;
4917
4918 STRV_FOREACH(i, search) {
4919 if (path_equal(parent, *i)) {
4920 r = 1;
4921 break;
4922 }
4923 }
4924
4925 free(parent);
4926
4927 return r;
4928}
4929
034a2a52
LP
4930int get_files_in_directory(const char *path, char ***list) {
4931 DIR *d;
4932 int r = 0;
4933 unsigned n = 0;
4934 char **l = NULL;
4935
4936 assert(path);
d60ef526
LP
4937
4938 /* Returns all files in a directory in *list, and the number
4939 * of files as return value. If list is NULL returns only the
4940 * number */
034a2a52
LP
4941
4942 d = opendir(path);
8ea913b2
LP
4943 if (!d)
4944 return -errno;
4945
034a2a52 4946 for (;;) {
7d5e9c0f
LP
4947 struct dirent *de;
4948 union dirent_storage buf;
034a2a52
LP
4949 int k;
4950
7d5e9c0f 4951 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
4952 if (k != 0) {
4953 r = -k;
4954 goto finish;
4955 }
4956
4957 if (!de)
4958 break;
4959
4960 dirent_ensure_type(d, de);
4961
4962 if (!dirent_is_file(de))
4963 continue;
4964
d60ef526
LP
4965 if (list) {
4966 if ((unsigned) r >= n) {
4967 char **t;
034a2a52 4968
d60ef526
LP
4969 n = MAX(16, 2*r);
4970 t = realloc(l, sizeof(char*) * n);
4971 if (!t) {
4972 r = -ENOMEM;
4973 goto finish;
4974 }
034a2a52 4975
d60ef526
LP
4976 l = t;
4977 }
034a2a52 4978
d60ef526 4979 assert((unsigned) r < n);
034a2a52 4980
d60ef526
LP
4981 l[r] = strdup(de->d_name);
4982 if (!l[r]) {
4983 r = -ENOMEM;
4984 goto finish;
4985 }
034a2a52 4986
d60ef526
LP
4987 l[++r] = NULL;
4988 } else
4989 r++;
034a2a52
LP
4990 }
4991
4992finish:
4993 if (d)
4994 closedir(d);
4995
d60ef526
LP
4996 if (r >= 0) {
4997 if (list)
4998 *list = l;
4999 } else
034a2a52
LP
5000 strv_free(l);
5001
5002 return r;
5003}
5004
b7def684 5005char *strjoin(const char *x, ...) {
911a4828
LP
5006 va_list ap;
5007 size_t l;
5008 char *r, *p;
5009
5010 va_start(ap, x);
5011
5012 if (x) {
5013 l = strlen(x);
5014
5015 for (;;) {
5016 const char *t;
5017
5018 t = va_arg(ap, const char *);
5019 if (!t)
5020 break;
5021
5022 l += strlen(t);
5023 }
5024 } else
5025 l = 0;
5026
5027 va_end(ap);
5028
5029 r = new(char, l+1);
5030 if (!r)
5031 return NULL;
5032
5033 if (x) {
5034 p = stpcpy(r, x);
5035
5036 va_start(ap, x);
5037
5038 for (;;) {
5039 const char *t;
5040
5041 t = va_arg(ap, const char *);
5042 if (!t)
5043 break;
5044
5045 p = stpcpy(p, t);
5046 }
8ea913b2
LP
5047
5048 va_end(ap);
911a4828
LP
5049 } else
5050 r[0] = 0;
5051
5052 return r;
5053}
5054
b636465b
LP
5055bool is_main_thread(void) {
5056 static __thread int cached = 0;
5057
5058 if (_unlikely_(cached == 0))
5059 cached = getpid() == gettid() ? 1 : -1;
5060
5061 return cached > 0;
5062}
5063
94959f0f
LP
5064int block_get_whole_disk(dev_t d, dev_t *ret) {
5065 char *p, *s;
5066 int r;
5067 unsigned n, m;
5068
5069 assert(ret);
5070
5071 /* If it has a queue this is good enough for us */
5072 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
5073 return -ENOMEM;
5074
5075 r = access(p, F_OK);
5076 free(p);
5077
5078 if (r >= 0) {
5079 *ret = d;
5080 return 0;
5081 }
5082
5083 /* If it is a partition find the originating device */
5084 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
5085 return -ENOMEM;
5086
5087 r = access(p, F_OK);
5088 free(p);
5089
5090 if (r < 0)
5091 return -ENOENT;
5092
5093 /* Get parent dev_t */
5094 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
5095 return -ENOMEM;
5096
5097 r = read_one_line_file(p, &s);
5098 free(p);
5099
5100 if (r < 0)
5101 return r;
5102
5103 r = sscanf(s, "%u:%u", &m, &n);
5104 free(s);
5105
5106 if (r != 2)
5107 return -EINVAL;
5108
5109 /* Only return this if it is really good enough for us. */
5110 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
5111 return -ENOMEM;
5112
5113 r = access(p, F_OK);
5114 free(p);
5115
5116 if (r >= 0) {
5117 *ret = makedev(m, n);
5118 return 0;
5119 }
5120
5121 return -ENOENT;
5122}
5123
8d53b453 5124int file_is_priv_sticky(const char *p) {
ad293f5a
LP
5125 struct stat st;
5126
5127 assert(p);
5128
5129 if (lstat(p, &st) < 0)
5130 return -errno;
5131
5132 return
8d53b453 5133 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
5134 (st.st_mode & S_ISVTX);
5135}
94959f0f 5136
f41607a6
LP
5137static const char *const ioprio_class_table[] = {
5138 [IOPRIO_CLASS_NONE] = "none",
5139 [IOPRIO_CLASS_RT] = "realtime",
5140 [IOPRIO_CLASS_BE] = "best-effort",
5141 [IOPRIO_CLASS_IDLE] = "idle"
5142};
5143
5144DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5145
5146static const char *const sigchld_code_table[] = {
5147 [CLD_EXITED] = "exited",
5148 [CLD_KILLED] = "killed",
5149 [CLD_DUMPED] = "dumped",
5150 [CLD_TRAPPED] = "trapped",
5151 [CLD_STOPPED] = "stopped",
5152 [CLD_CONTINUED] = "continued",
5153};
5154
5155DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5156
5157static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5158 [LOG_FAC(LOG_KERN)] = "kern",
5159 [LOG_FAC(LOG_USER)] = "user",
5160 [LOG_FAC(LOG_MAIL)] = "mail",
5161 [LOG_FAC(LOG_DAEMON)] = "daemon",
5162 [LOG_FAC(LOG_AUTH)] = "auth",
5163 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5164 [LOG_FAC(LOG_LPR)] = "lpr",
5165 [LOG_FAC(LOG_NEWS)] = "news",
5166 [LOG_FAC(LOG_UUCP)] = "uucp",
5167 [LOG_FAC(LOG_CRON)] = "cron",
5168 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5169 [LOG_FAC(LOG_FTP)] = "ftp",
5170 [LOG_FAC(LOG_LOCAL0)] = "local0",
5171 [LOG_FAC(LOG_LOCAL1)] = "local1",
5172 [LOG_FAC(LOG_LOCAL2)] = "local2",
5173 [LOG_FAC(LOG_LOCAL3)] = "local3",
5174 [LOG_FAC(LOG_LOCAL4)] = "local4",
5175 [LOG_FAC(LOG_LOCAL5)] = "local5",
5176 [LOG_FAC(LOG_LOCAL6)] = "local6",
5177 [LOG_FAC(LOG_LOCAL7)] = "local7"
5178};
5179
5180DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5181
5182static const char *const log_level_table[] = {
5183 [LOG_EMERG] = "emerg",
5184 [LOG_ALERT] = "alert",
5185 [LOG_CRIT] = "crit",
5186 [LOG_ERR] = "err",
5187 [LOG_WARNING] = "warning",
5188 [LOG_NOTICE] = "notice",
5189 [LOG_INFO] = "info",
5190 [LOG_DEBUG] = "debug"
5191};
5192
5193DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5194
5195static const char* const sched_policy_table[] = {
5196 [SCHED_OTHER] = "other",
5197 [SCHED_BATCH] = "batch",
5198 [SCHED_IDLE] = "idle",
5199 [SCHED_FIFO] = "fifo",
5200 [SCHED_RR] = "rr"
5201};
5202
5203DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5204
5205static const char* const rlimit_table[] = {
5206 [RLIMIT_CPU] = "LimitCPU",
5207 [RLIMIT_FSIZE] = "LimitFSIZE",
5208 [RLIMIT_DATA] = "LimitDATA",
5209 [RLIMIT_STACK] = "LimitSTACK",
5210 [RLIMIT_CORE] = "LimitCORE",
5211 [RLIMIT_RSS] = "LimitRSS",
5212 [RLIMIT_NOFILE] = "LimitNOFILE",
5213 [RLIMIT_AS] = "LimitAS",
5214 [RLIMIT_NPROC] = "LimitNPROC",
5215 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5216 [RLIMIT_LOCKS] = "LimitLOCKS",
5217 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5218 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5219 [RLIMIT_NICE] = "LimitNICE",
5220 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5221 [RLIMIT_RTTIME] = "LimitRTTIME"
5222};
5223
5224DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5225
5226static const char* const ip_tos_table[] = {
5227 [IPTOS_LOWDELAY] = "low-delay",
5228 [IPTOS_THROUGHPUT] = "throughput",
5229 [IPTOS_RELIABILITY] = "reliability",
5230 [IPTOS_LOWCOST] = "low-cost",
5231};
5232
5233DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5234
4e240ab0 5235static const char *const __signal_table[] = {
f41607a6
LP
5236 [SIGHUP] = "HUP",
5237 [SIGINT] = "INT",
5238 [SIGQUIT] = "QUIT",
5239 [SIGILL] = "ILL",
5240 [SIGTRAP] = "TRAP",
5241 [SIGABRT] = "ABRT",
5242 [SIGBUS] = "BUS",
5243 [SIGFPE] = "FPE",
5244 [SIGKILL] = "KILL",
5245 [SIGUSR1] = "USR1",
5246 [SIGSEGV] = "SEGV",
5247 [SIGUSR2] = "USR2",
5248 [SIGPIPE] = "PIPE",
5249 [SIGALRM] = "ALRM",
5250 [SIGTERM] = "TERM",
5251#ifdef SIGSTKFLT
5252 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5253#endif
5254 [SIGCHLD] = "CHLD",
5255 [SIGCONT] = "CONT",
5256 [SIGSTOP] = "STOP",
5257 [SIGTSTP] = "TSTP",
5258 [SIGTTIN] = "TTIN",
5259 [SIGTTOU] = "TTOU",
5260 [SIGURG] = "URG",
5261 [SIGXCPU] = "XCPU",
5262 [SIGXFSZ] = "XFSZ",
5263 [SIGVTALRM] = "VTALRM",
5264 [SIGPROF] = "PROF",
5265 [SIGWINCH] = "WINCH",
5266 [SIGIO] = "IO",
5267 [SIGPWR] = "PWR",
5268 [SIGSYS] = "SYS"
5269};
5270
4e240ab0
MS
5271DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5272
5273const char *signal_to_string(int signo) {
5274 static __thread char buf[12];
5275 const char *name;
5276
5277 name = __signal_to_string(signo);
5278 if (name)
5279 return name;
5280
5281 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
5282 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
5283 else
5284 snprintf(buf, sizeof(buf) - 1, "%d", signo);
5285 char_array_0(buf);
5286 return buf;
5287}
5288
5289int signal_from_string(const char *s) {
5290 int signo;
5291 int offset = 0;
5292 unsigned u;
5293
5294 signo =__signal_from_string(s);
5295 if (signo > 0)
5296 return signo;
5297
5298 if (startswith(s, "RTMIN+")) {
5299 s += 6;
5300 offset = SIGRTMIN;
5301 }
5302 if (safe_atou(s, &u) >= 0) {
5303 signo = (int) u + offset;
5304 if (signo > 0 && signo < _NSIG)
5305 return signo;
5306 }
5307 return -1;
5308}
65457142
FC
5309
5310bool kexec_loaded(void) {
5311 bool loaded = false;
5312 char *s;
5313
5314 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5315 if (s[0] == '1')
5316 loaded = true;
5317 free(s);
5318 }
5319 return loaded;
5320}
fb9de93d
LP
5321
5322int strdup_or_null(const char *a, char **b) {
5323 char *c;
5324
5325 assert(b);
5326
5327 if (!a) {
5328 *b = NULL;
5329 return 0;
5330 }
5331
5332 c = strdup(a);
5333 if (!c)
5334 return -ENOMEM;
5335
5336 *b = c;
5337 return 0;
5338}
64685e0c 5339
87d2c1ff
LP
5340int prot_from_flags(int flags) {
5341
5342 switch (flags & O_ACCMODE) {
5343
5344 case O_RDONLY:
5345 return PROT_READ;
5346
5347 case O_WRONLY:
5348 return PROT_WRITE;
5349
5350 case O_RDWR:
5351 return PROT_READ|PROT_WRITE;
5352
5353 default:
5354 return -EINVAL;
5355 }
7c99e0c1 5356}
689b9a22 5357
babfc091 5358char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5359 unsigned i;
babfc091
LP
5360
5361 static const struct {
5362 const char *suffix;
5363 off_t factor;
5364 } table[] = {
32895bb3
LP
5365 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5366 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5367 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5368 { "G", 1024ULL*1024ULL*1024ULL },
5369 { "M", 1024ULL*1024ULL },
5370 { "K", 1024ULL },
5371 };
5372
5373 for (i = 0; i < ELEMENTSOF(table); i++) {
5374
5375 if (t >= table[i].factor) {
5376 snprintf(buf, l,
5377 "%llu.%llu%s",
5378 (unsigned long long) (t / table[i].factor),
5379 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5380 table[i].suffix);
5381
5382 goto finish;
5383 }
5384 }
5385
5386 snprintf(buf, l, "%lluB", (unsigned long long) t);
5387
5388finish:
5389 buf[l-1] = 0;
5390 return buf;
5391
5392}
55d7bfc1
LP
5393
5394void* memdup(const void *p, size_t l) {
5395 void *r;
5396
5397 assert(p);
5398
5399 r = malloc(l);
5400 if (!r)
5401 return NULL;
5402
5403 memcpy(r, p, l);
5404 return r;
5405}
bb99a35a
LP
5406
5407int fd_inc_sndbuf(int fd, size_t n) {
5408 int r, value;
5409 socklen_t l = sizeof(value);
5410
5411 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
5412 if (r >= 0 &&
5413 l == sizeof(value) &&
5414 (size_t) value >= n*2)
5415 return 0;
5416
5417 value = (int) n;
5418 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
5419 if (r < 0)
5420 return -errno;
5421
5422 return 1;
5423}
5424
5425int fd_inc_rcvbuf(int fd, size_t n) {
5426 int r, value;
5427 socklen_t l = sizeof(value);
5428
5429 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
5430 if (r >= 0 &&
5431 l == sizeof(value) &&
5432 (size_t) value >= n*2)
5433 return 0;
5434
5435 value = (int) n;
5436 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
5437 if (r < 0)
5438 return -errno;
5439
5440 return 1;
5441}
6bb92a16 5442
9bdc770c 5443int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
5444 pid_t parent_pid, agent_pid;
5445 int fd;
5446 bool stdout_is_tty, stderr_is_tty;
5447 unsigned n, i;
5448 va_list ap;
5449 char **l;
5450
5451 assert(pid);
5452 assert(path);
5453
5454 parent_pid = getpid();
5455
5456 /* Spawns a temporary TTY agent, making sure it goes away when
5457 * we go away */
5458
5459 agent_pid = fork();
5460 if (agent_pid < 0)
5461 return -errno;
5462
5463 if (agent_pid != 0) {
5464 *pid = agent_pid;
5465 return 0;
5466 }
5467
5468 /* In the child:
5469 *
5470 * Make sure the agent goes away when the parent dies */
5471 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5472 _exit(EXIT_FAILURE);
5473
5474 /* Check whether our parent died before we were able
5475 * to set the death signal */
5476 if (getppid() != parent_pid)
5477 _exit(EXIT_SUCCESS);
5478
5479 /* Don't leak fds to the agent */
9bdc770c 5480 close_all_fds(except, n_except);
6bb92a16
LP
5481
5482 stdout_is_tty = isatty(STDOUT_FILENO);
5483 stderr_is_tty = isatty(STDERR_FILENO);
5484
5485 if (!stdout_is_tty || !stderr_is_tty) {
5486 /* Detach from stdout/stderr. and reopen
5487 * /dev/tty for them. This is important to
5488 * ensure that when systemctl is started via
5489 * popen() or a similar call that expects to
5490 * read EOF we actually do generate EOF and
5491 * not delay this indefinitely by because we
5492 * keep an unused copy of stdin around. */
5493 fd = open("/dev/tty", O_WRONLY);
5494 if (fd < 0) {
5495 log_error("Failed to open /dev/tty: %m");
5496 _exit(EXIT_FAILURE);
5497 }
5498
5499 if (!stdout_is_tty)
5500 dup2(fd, STDOUT_FILENO);
5501
5502 if (!stderr_is_tty)
5503 dup2(fd, STDERR_FILENO);
5504
5505 if (fd > 2)
5506 close(fd);
5507 }
5508
5509 /* Count arguments */
5510 va_start(ap, path);
5511 for (n = 0; va_arg(ap, char*); n++)
5512 ;
5513 va_end(ap);
5514
5515 /* Allocate strv */
5516 l = alloca(sizeof(char *) * (n + 1));
5517
5518 /* Fill in arguments */
5519 va_start(ap, path);
5520 for (i = 0; i <= n; i++)
5521 l[i] = va_arg(ap, char*);
5522 va_end(ap);
5523
5524 execv(path, l);
5525 _exit(EXIT_FAILURE);
5526}
68faf98c
LP
5527
5528int setrlimit_closest(int resource, const struct rlimit *rlim) {
5529 struct rlimit highest, fixed;
5530
5531 assert(rlim);
5532
5533 if (setrlimit(resource, rlim) >= 0)
5534 return 0;
5535
5536 if (errno != EPERM)
5537 return -errno;
5538
5539 /* So we failed to set the desired setrlimit, then let's try
5540 * to get as close as we can */
5541 assert_se(getrlimit(resource, &highest) == 0);
5542
5543 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5544 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5545
5546 if (setrlimit(resource, &fixed) < 0)
5547 return -errno;
5548
5549 return 0;
5550}
3d9a4122 5551
ab94af92
LP
5552int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5553 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5554 int r;
5555 FILE *f;
5556 bool done = false;
5557 size_t l;
5558
5559 assert(field);
5560 assert(_value);
5561
5562 if (pid == 0)
5563 pid = getpid();
5564
5565 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5566 char_array_0(path);
5567
5568 f = fopen(path, "re");
5569 if (!f)
5570 return -errno;
5571
5572 l = strlen(field);
5573 r = 0;
5574
5575 do {
5576 char line[LINE_MAX];
5577 unsigned i;
5578
5579 for (i = 0; i < sizeof(line)-1; i++) {
5580 int c;
5581
5582 c = getc(f);
5583 if (_unlikely_(c == EOF)) {
5584 done = true;
5585 break;
5586 } else if (c == 0)
5587 break;
5588
5589 line[i] = c;
5590 }
5591 line[i] = 0;
5592
5593 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5594 value = strdup(line + l + 1);
5595 if (!value) {
5596 r = -ENOMEM;
5597 break;
5598 }
5599
5600 r = 1;
5601 break;
5602 }
5603
5604 } while (!done);
5605
5606 fclose(f);
5607
5608 if (r >= 0)
5609 *_value = value;
5610
5611 return r;
5612}
d889a206
LP
5613
5614int can_sleep(const char *type) {
e67f47e5 5615 char *w, *state;
d889a206 5616 size_t l, k;
d889a206 5617 int r;
e67f47e5 5618 _cleanup_free_ char *p = NULL;
d889a206
LP
5619
5620 assert(type);
5621
5622 r = read_one_line_file("/sys/power/state", &p);
5623 if (r < 0)
5624 return r == -ENOENT ? 0 : r;
5625
5626 k = strlen(type);
e67f47e5
LP
5627 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
5628 if (l == k && memcmp(w, type, l) == 0)
5629 return true;
d889a206 5630
e67f47e5 5631 return false;
d889a206 5632}
49dbfa7b
LP
5633
5634bool is_valid_documentation_url(const char *url) {
5635 assert(url);
5636
5637 if (startswith(url, "http://") && url[7])
5638 return true;
5639
5640 if (startswith(url, "https://") && url[8])
5641 return true;
5642
5643 if (startswith(url, "file:") && url[5])
5644 return true;
5645
5646 if (startswith(url, "info:") && url[5])
5647 return true;
5648
5649 if (startswith(url, "man:") && url[4])
5650 return true;
5651
5652 return false;
5653}
9be346c9
HH
5654
5655bool in_initrd(void) {
a05f97b3 5656 static __thread int saved = -1;
825c6fe5 5657 struct statfs s;
8f33b5b8 5658
825c6fe5
LP
5659 if (saved >= 0)
5660 return saved;
5661
5662 /* We make two checks here:
5663 *
5664 * 1. the flag file /etc/initrd-release must exist
5665 * 2. the root file system must be a memory file system
5666 *
5667 * The second check is extra paranoia, since misdetecting an
5668 * initrd can have bad bad consequences due the initrd
5669 * emptying when transititioning to the main systemd.
5670 */
5671
5672 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5673 statfs("/", &s) >= 0 &&
5674 (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
9be346c9 5675
8f33b5b8 5676 return saved;
9be346c9 5677}
069cfc85
LP
5678
5679void warn_melody(void) {
e67f47e5 5680 _cleanup_close_ int fd = -1;
069cfc85
LP
5681
5682 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5683 if (fd < 0)
5684 return;
5685
5686 /* Yeah, this is synchronous. Kinda sucks. Bute well... */
5687
5688 ioctl(fd, KIOCSOUND, (int)(1193180/440));
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, (int)(1193180/220));
5695 usleep(125*USEC_PER_MSEC);
5696
5697 ioctl(fd, KIOCSOUND, 0);
069cfc85 5698}
cd3bd60a
LP
5699
5700int make_console_stdio(void) {
5701 int fd, r;
5702
5703 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5704
5705 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5706 if (fd < 0) {
5707 log_error("Failed to acquire terminal: %s", strerror(-fd));
5708 return fd;
5709 }
5710
5711 r = make_stdio(fd);
5712 if (r < 0) {
5713 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5714 return r;
5715 }
5716
5717 return 0;
5718}
7c5f152a
LP
5719
5720int get_home_dir(char **_h) {
5721 char *h;
5722 const char *e;
5723 uid_t u;
5724 struct passwd *p;
5725
5726 assert(_h);
5727
5728 /* Take the user specified one */
5729 e = getenv("HOME");
5730 if (e) {
5731 h = strdup(e);
5732 if (!h)
5733 return -ENOMEM;
5734
5735 *_h = h;
5736 return 0;
5737 }
5738
5739 /* Hardcode home directory for root to avoid NSS */
5740 u = getuid();
5741 if (u == 0) {
5742 h = strdup("/root");
5743 if (!h)
5744 return -ENOMEM;
5745
5746 *_h = h;
5747 return 0;
5748 }
5749
5750 /* Check the database... */
5751 errno = 0;
5752 p = getpwuid(u);
5753 if (!p)
e67f47e5 5754 return errno ? -errno : -ESRCH;
7c5f152a
LP
5755
5756 if (!path_is_absolute(p->pw_dir))
5757 return -EINVAL;
5758
5759 h = strdup(p->pw_dir);
5760 if (!h)
5761 return -ENOMEM;
5762
5763 *_h = h;
5764 return 0;
5765}
5766
5767int get_shell(char **_sh) {
5768 char *sh;
5769 const char *e;
5770 uid_t u;
5771 struct passwd *p;
5772
5773 assert(_sh);
5774
5775 /* Take the user specified one */
5776 e = getenv("SHELL");
5777 if (e) {
5778 sh = strdup(e);
5779 if (!sh)
5780 return -ENOMEM;
5781
5782 *_sh = sh;
5783 return 0;
5784 }
5785
5786 /* Hardcode home directory for root to avoid NSS */
5787 u = getuid();
5788 if (u == 0) {
5789 sh = strdup("/bin/sh");
5790 if (!sh)
5791 return -ENOMEM;
5792
5793 *_sh = sh;
5794 return 0;
5795 }
5796
5797 /* Check the database... */
5798 errno = 0;
5799 p = getpwuid(u);
5800 if (!p)
5801 return errno ? -errno : -ESRCH;
5802
5803 if (!path_is_absolute(p->pw_shell))
5804 return -EINVAL;
5805
5806 sh = strdup(p->pw_shell);
5807 if (!sh)
5808 return -ENOMEM;
5809
5810 *_sh = sh;
5811 return 0;
5812}
2fbe635a
LP
5813
5814void freep(void *p) {
5815 free(*(void**) p);
5816}
5817
5818void fclosep(FILE **f) {
5819 if (*f)
5820 fclose(*f);
5821}
e67f47e5
LP
5822
5823void closep(int *fd) {
5824 if (*fd >= 0)
5825 close_nointr_nofail(*fd);
5826}
a05f97b3
LP
5827
5828void closedirp(DIR **d) {
5829 if (*d)
5830 closedir(*d);
5831}
25ea79fe
ZJS
5832
5833void umaskp(mode_t *u) {
5834 umask(*u);
5835}