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