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