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