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