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