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