]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/util.c
add a few O_CLOEXEC where missing
[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
2950 return 0;
2951}
2952
ade509ce
LP
2953int make_null_stdio(void) {
2954 int null_fd;
2955
2956 if ((null_fd = open("/dev/null", O_RDWR|O_NOCTTY)) < 0)
2957 return -errno;
2958
2959 return make_stdio(null_fd);
2960}
2961
8407a5d0
LP
2962bool is_device_path(const char *path) {
2963
2964 /* Returns true on paths that refer to a device, either in
2965 * sysfs or in /dev */
2966
2967 return
2968 path_startswith(path, "/dev/") ||
2969 path_startswith(path, "/sys/");
2970}
2971
01f78473
LP
2972int dir_is_empty(const char *path) {
2973 DIR *d;
2974 int r;
2975 struct dirent buf, *de;
2976
2977 if (!(d = opendir(path)))
2978 return -errno;
2979
2980 for (;;) {
2981 if ((r = readdir_r(d, &buf, &de)) > 0) {
2982 r = -r;
2983 break;
2984 }
2985
2986 if (!de) {
2987 r = 1;
2988 break;
2989 }
2990
2991 if (!ignore_file(de->d_name)) {
2992 r = 0;
2993 break;
2994 }
2995 }
2996
2997 closedir(d);
2998 return r;
2999}
3000
d3782d60
LP
3001unsigned long long random_ull(void) {
3002 int fd;
3003 uint64_t ull;
3004 ssize_t r;
3005
3006 if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0)
3007 goto fallback;
3008
eb22ac37 3009 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
3010 close_nointr_nofail(fd);
3011
3012 if (r != sizeof(ull))
3013 goto fallback;
3014
3015 return ull;
3016
3017fallback:
3018 return random() * RAND_MAX + random();
3019}
3020
5b6319dc
LP
3021void rename_process(const char name[8]) {
3022 assert(name);
3023
3024 prctl(PR_SET_NAME, name);
3025
3026 /* This is a like a poor man's setproctitle(). The string
3027 * passed should fit in 7 chars (i.e. the length of
3028 * "systemd") */
3029
3030 if (program_invocation_name)
3031 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
3032
3033 if (saved_argc > 0) {
3034 int i;
3035
3036 if (saved_argv[0])
3037 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
3038
3039 for (i = 1; i < saved_argc; i++) {
3040 if (!saved_argv[i])
3041 break;
3042
3043 memset(saved_argv[i], 0, strlen(saved_argv[i]));
3044 }
3045 }
5b6319dc
LP
3046}
3047
7d793605
LP
3048void sigset_add_many(sigset_t *ss, ...) {
3049 va_list ap;
3050 int sig;
3051
3052 assert(ss);
3053
3054 va_start(ap, ss);
3055 while ((sig = va_arg(ap, int)) > 0)
3056 assert_se(sigaddset(ss, sig) == 0);
3057 va_end(ap);
3058}
3059
ef2f1067
LP
3060char* gethostname_malloc(void) {
3061 struct utsname u;
3062
3063 assert_se(uname(&u) >= 0);
3064
3065 if (u.nodename[0])
3066 return strdup(u.nodename);
3067
3068 return strdup(u.sysname);
3069}
3070
3071char* getlogname_malloc(void) {
3072 uid_t uid;
3073 long bufsize;
3074 char *buf, *name;
3075 struct passwd pwbuf, *pw = NULL;
3076 struct stat st;
3077
3078 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
3079 uid = st.st_uid;
3080 else
3081 uid = getuid();
3082
3083 /* Shortcut things to avoid NSS lookups */
3084 if (uid == 0)
3085 return strdup("root");
3086
3087 if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) <= 0)
3088 bufsize = 4096;
3089
3090 if (!(buf = malloc(bufsize)))
3091 return NULL;
3092
3093 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
3094 name = strdup(pw->pw_name);
3095 free(buf);
3096 return name;
3097 }
3098
3099 free(buf);
3100
3101 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
3102 return NULL;
3103
3104 return name;
3105}
3106
fc116c6a
LP
3107int getttyname_malloc(int fd, char **r) {
3108 char path[PATH_MAX], *c;
618e02c7 3109 int k;
8c6db833
LP
3110
3111 assert(r);
ef2f1067 3112
fc116c6a 3113 if ((k = ttyname_r(fd, path, sizeof(path))) != 0)
618e02c7 3114 return -k;
ef2f1067
LP
3115
3116 char_array_0(path);
3117
fc116c6a 3118 if (!(c = strdup(startswith(path, "/dev/") ? path + 5 : path)))
8c6db833
LP
3119 return -ENOMEM;
3120
3121 *r = c;
3122 return 0;
3123}
3124
fc116c6a
LP
3125int getttyname_harder(int fd, char **r) {
3126 int k;
3127 char *s;
3128
3129 if ((k = getttyname_malloc(fd, &s)) < 0)
3130 return k;
3131
3132 if (streq(s, "tty")) {
3133 free(s);
4d6d6518 3134 return get_ctty(0, NULL, r);
fc116c6a
LP
3135 }
3136
3137 *r = s;
3138 return 0;
3139}
3140
4d6d6518 3141int get_ctty_devnr(pid_t pid, dev_t *d) {
fc116c6a 3142 int k;
4d6d6518 3143 char line[LINE_MAX], *p, *fn;
fc116c6a
LP
3144 unsigned long ttynr;
3145 FILE *f;
3146
4d6d6518
LP
3147 if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
3148 return -ENOMEM;
3149
3150 f = fopen(fn, "re");
3151 free(fn);
3152 if (!f)
fc116c6a
LP
3153 return -errno;
3154
4d6d6518 3155 if (!fgets(line, sizeof(line), f)) {
fc116c6a
LP
3156 k = -errno;
3157 fclose(f);
3158 return k;
3159 }
3160
3161 fclose(f);
3162
4d6d6518
LP
3163 p = strrchr(line, ')');
3164 if (!p)
fc116c6a
LP
3165 return -EIO;
3166
3167 p++;
3168
3169 if (sscanf(p, " "
3170 "%*c " /* state */
3171 "%*d " /* ppid */
3172 "%*d " /* pgrp */
3173 "%*d " /* session */
3174 "%lu ", /* ttynr */
3175 &ttynr) != 1)
3176 return -EIO;
3177
3178 *d = (dev_t) ttynr;
3179 return 0;
3180}
3181
4d6d6518 3182int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 3183 int k;
20c03b7b 3184 char fn[PATH_MAX], *s, *b, *p;
fc116c6a
LP
3185 dev_t devnr;
3186
3187 assert(r);
3188
4d6d6518
LP
3189 k = get_ctty_devnr(pid, &devnr);
3190 if (k < 0)
fc116c6a
LP
3191 return k;
3192
3193 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
3194 char_array_0(fn);
3195
3196 if ((k = readlink_malloc(fn, &s)) < 0) {
3197
3198 if (k != -ENOENT)
3199 return k;
3200
46824d0e
LP
3201 /* This is an ugly hack */
3202 if (major(devnr) == 136) {
3203 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
3204 return -ENOMEM;
3205
3206 *r = b;
3207 if (_devnr)
3208 *_devnr = devnr;
3209
3210 return 0;
3211 }
3212
fc116c6a
LP
3213 /* Probably something like the ptys which have no
3214 * symlink in /dev/char. Let's return something
3215 * vaguely useful. */
3216
3217 if (!(b = strdup(fn + 5)))
3218 return -ENOMEM;
3219
3220 *r = b;
46824d0e
LP
3221 if (_devnr)
3222 *_devnr = devnr;
3223
fc116c6a
LP
3224 return 0;
3225 }
3226
3227 if (startswith(s, "/dev/"))
3228 p = s + 5;
3229 else if (startswith(s, "../"))
3230 p = s + 3;
3231 else
3232 p = s;
3233
3234 b = strdup(p);
3235 free(s);
3236
3237 if (!b)
3238 return -ENOMEM;
3239
3240 *r = b;
46824d0e
LP
3241 if (_devnr)
3242 *_devnr = devnr;
3243
fc116c6a
LP
3244 return 0;
3245}
3246
8c6db833
LP
3247static int rm_rf_children(int fd, bool only_dirs) {
3248 DIR *d;
3249 int ret = 0;
3250
3251 assert(fd >= 0);
3252
3253 /* This returns the first error we run into, but nevertheless
3254 * tries to go on */
3255
3256 if (!(d = fdopendir(fd))) {
3257 close_nointr_nofail(fd);
4c633005
LP
3258
3259 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
3260 }
3261
3262 for (;;) {
3263 struct dirent buf, *de;
3264 bool is_dir;
3265 int r;
3266
3267 if ((r = readdir_r(d, &buf, &de)) != 0) {
3268 if (ret == 0)
3269 ret = -r;
3270 break;
3271 }
3272
3273 if (!de)
3274 break;
3275
3276 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
3277 continue;
3278
3279 if (de->d_type == DT_UNKNOWN) {
3280 struct stat st;
3281
3282 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 3283 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3284 ret = -errno;
3285 continue;
3286 }
3287
3288 is_dir = S_ISDIR(st.st_mode);
3289 } else
3290 is_dir = de->d_type == DT_DIR;
3291
3292 if (is_dir) {
3293 int subdir_fd;
3294
3295 if ((subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
4c633005 3296 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3297 ret = -errno;
3298 continue;
3299 }
3300
3301 if ((r = rm_rf_children(subdir_fd, only_dirs)) < 0) {
3302 if (ret == 0)
3303 ret = r;
3304 }
3305
3306 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
4c633005 3307 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3308 ret = -errno;
3309 }
3310 } else if (!only_dirs) {
3311
3312 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 3313 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3314 ret = -errno;
3315 }
3316 }
3317 }
3318
3319 closedir(d);
3320
3321 return ret;
3322}
3323
3324int rm_rf(const char *path, bool only_dirs, bool delete_root) {
3325 int fd;
3326 int r;
3327
3328 assert(path);
3329
3330 if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
3331
3332 if (errno != ENOTDIR)
3333 return -errno;
3334
3335 if (delete_root && !only_dirs)
3336 if (unlink(path) < 0)
3337 return -errno;
3338
3339 return 0;
3340 }
3341
3342 r = rm_rf_children(fd, only_dirs);
3343
3344 if (delete_root)
3345 if (rmdir(path) < 0) {
3346 if (r == 0)
3347 r = -errno;
3348 }
3349
3350 return r;
3351}
3352
3353int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
3354 assert(path);
3355
3356 /* Under the assumption that we are running privileged we
3357 * first change the access mode and only then hand out
3358 * ownership to avoid a window where access is too open. */
3359
3360 if (chmod(path, mode) < 0)
3361 return -errno;
3362
3363 if (chown(path, uid, gid) < 0)
3364 return -errno;
3365
3366 return 0;
ef2f1067
LP
3367}
3368
82c121a4
LP
3369cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
3370 cpu_set_t *r;
3371 unsigned n = 1024;
3372
3373 /* Allocates the cpuset in the right size */
3374
3375 for (;;) {
3376 if (!(r = CPU_ALLOC(n)))
3377 return NULL;
3378
3379 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
3380 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
3381
3382 if (ncpus)
3383 *ncpus = n;
3384
3385 return r;
3386 }
3387
3388 CPU_FREE(r);
3389
3390 if (errno != EINVAL)
3391 return NULL;
3392
3393 n *= 2;
3394 }
3395}
3396
9e58ff9c
LP
3397void status_vprintf(const char *format, va_list ap) {
3398 char *s = NULL;
3399 int fd = -1;
3400
3401 assert(format);
3402
3403 /* This independent of logging, as status messages are
3404 * optional and go exclusively to the console. */
3405
3406 if (vasprintf(&s, format, ap) < 0)
3407 goto finish;
3408
3409 if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
3410 goto finish;
3411
3412 write(fd, s, strlen(s));
3413
3414finish:
3415 free(s);
3416
3417 if (fd >= 0)
3418 close_nointr_nofail(fd);
3419}
3420
c846ff47
LP
3421void status_printf(const char *format, ...) {
3422 va_list ap;
3423
3424 assert(format);
3425
3426 va_start(ap, format);
3427 status_vprintf(format, ap);
3428 va_end(ap);
3429}
3430
3431void status_welcome(void) {
10aa7034
LP
3432 char *pretty_name = NULL, *ansi_color = NULL;
3433 const char *const_pretty = NULL, *const_color = NULL;
3434 int r;
c846ff47 3435
10aa7034
LP
3436 if ((r = parse_env_file("/etc/os-release", NEWLINE,
3437 "PRETTY_NAME", &pretty_name,
3438 "ANSI_COLOR", &ansi_color,
3439 NULL)) < 0) {
c846ff47 3440
10aa7034
LP
3441 if (r != -ENOENT)
3442 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3443 }
c846ff47 3444
10aa7034
LP
3445#if defined(TARGET_FEDORA)
3446 if (!pretty_name) {
3447 if ((r = read_one_line_file("/etc/system-release", &pretty_name)) < 0) {
c846ff47 3448
10aa7034
LP
3449 if (r != -ENOENT)
3450 log_warning("Failed to read /etc/system-release: %s", strerror(-r));
6f9a471a 3451 }
10aa7034 3452 }
c846ff47 3453
10aa7034 3454 if (!ansi_color && pretty_name) {
c846ff47 3455
10aa7034
LP
3456 /* This tries to mimic the color magic the old Red Hat sysinit
3457 * script did. */
3458
3459 if (startswith(pretty_name, "Red Hat"))
3460 const_color = "0;31"; /* Red for RHEL */
3461 else if (startswith(pretty_name, "Fedora"))
3462 const_color = "0;34"; /* Blue for Fedora */
3463 }
c846ff47
LP
3464
3465#elif defined(TARGET_SUSE)
c846ff47 3466
10aa7034
LP
3467 if (!pretty_name) {
3468 if ((r = read_one_line_file("/etc/SuSE-release", &pretty_name)) < 0) {
c846ff47 3469
10aa7034
LP
3470 if (r != -ENOENT)
3471 log_warning("Failed to read /etc/SuSE-release: %s", strerror(-r));
6f9a471a 3472 }
10aa7034 3473 }
c846ff47 3474
10aa7034
LP
3475 if (!ansi_color)
3476 const_color = "0;32"; /* Green for openSUSE */
5a6225fd 3477
0d37b36b 3478#elif defined(TARGET_GENTOO)
0d37b36b 3479
10aa7034
LP
3480 if (!pretty_name) {
3481 if ((r = read_one_line_file("/etc/gentoo-release", &pretty_name)) < 0) {
0d37b36b 3482
10aa7034
LP
3483 if (r != -ENOENT)
3484 log_warning("Failed to read /etc/gentoo-release: %s", strerror(-r));
6f9a471a 3485 }
10aa7034 3486 }
0d37b36b 3487
10aa7034
LP
3488 if (!ansi_color)
3489 const_color = "1;34"; /* Light Blue for Gentoo */
5a6225fd 3490
a338bab5
AS
3491#elif defined(TARGET_ALTLINUX)
3492
3493 if (!pretty_name) {
3494 if ((r = read_one_line_file("/etc/altlinux-release", &pretty_name)) < 0) {
3495
3496 if (r != -ENOENT)
3497 log_warning("Failed to read /etc/altlinux-release: %s", strerror(-r));
6f9a471a 3498 }
a338bab5
AS
3499 }
3500
3501 if (!ansi_color)
3502 const_color = "0;36"; /* Cyan for ALTLinux */
3503
3504
5a6225fd 3505#elif defined(TARGET_DEBIAN)
5a6225fd 3506
10aa7034 3507 if (!pretty_name) {
22927a36 3508 char *version;
c8bffa43 3509
22927a36 3510 if ((r = read_one_line_file("/etc/debian_version", &version)) < 0) {
5a6225fd 3511
10aa7034
LP
3512 if (r != -ENOENT)
3513 log_warning("Failed to read /etc/debian_version: %s", strerror(-r));
22927a36 3514 } else {
22927a36
MB
3515 pretty_name = strappend("Debian ", version);
3516 free(version);
c8bffa43
LP
3517
3518 if (!pretty_name)
3519 log_warning("Failed to allocate Debian version string.");
22927a36 3520 }
10aa7034 3521 }
5a6225fd 3522
10aa7034
LP
3523 if (!ansi_color)
3524 const_color = "1;31"; /* Light Red for Debian */
5a6225fd 3525
274914f9 3526#elif defined(TARGET_UBUNTU)
10aa7034
LP
3527
3528 if ((r = parse_env_file("/etc/lsb-release", NEWLINE,
3529 "DISTRIB_DESCRIPTION", &pretty_name,
3530 NULL)) < 0) {
3531
3532 if (r != -ENOENT)
3533 log_warning("Failed to read /etc/lsb-release: %s", strerror(-r));
3534 }
3535
3536 if (!ansi_color)
3537 const_color = "0;33"; /* Orange/Brown for Ubuntu */
3538
1de4d79b
AB
3539#elif defined(TARGET_MANDRIVA)
3540
3541 if (!pretty_name) {
3542 char *s, *p;
3543
3544 if ((r = read_one_line_file("/etc/mandriva-release", &s) < 0)) {
3545 if (r != -ENOENT)
3546 log_warning("Failed to read /etc/mandriva-release: %s", strerror(-r));
3547 } else {
3548 p = strstr(s, " release ");
3549 if (p) {
3550 *p = '\0';
3551 p += 9;
3552 p[strcspn(p, " ")] = '\0';
3553
3554 /* This corresponds to standard rc.sysinit */
3555 if (asprintf(&pretty_name, "%s\x1B[0;39m %s", s, p) > 0)
3556 const_color = "1;36";
3557 else
3558 log_warning("Failed to allocate Mandriva version string.");
3559 } else
3560 log_warning("Failed to parse /etc/mandriva-release");
3561 free(s);
3562 }
3563 }
54e4fdef 3564#elif defined(TARGET_MEEGO)
1de4d79b 3565
54e4fdef
CF
3566 if (!pretty_name) {
3567 if ((r = read_one_line_file("/etc/meego-release", &pretty_name)) < 0) {
3568
3569 if (r != -ENOENT)
3570 log_warning("Failed to read /etc/meego-release: %s", strerror(-r));
3571 }
3572 }
3573
3574 if (!ansi_color)
3575 const_color = "1;35"; /* Bright Magenta for MeeGo */
c846ff47 3576#endif
10aa7034
LP
3577
3578 if (!pretty_name && !const_pretty)
3579 const_pretty = "Linux";
3580
3581 if (!ansi_color && !const_color)
3582 const_color = "1";
3583
da71f23c 3584 status_printf("\nWelcome to \x1B[%sm%s\x1B[0m!\n\n",
10aa7034
LP
3585 const_color ? const_color : ansi_color,
3586 const_pretty ? const_pretty : pretty_name);
86a3475b
LP
3587
3588 free(ansi_color);
3589 free(pretty_name);
c846ff47
LP
3590}
3591
fab56fc5
LP
3592char *replace_env(const char *format, char **env) {
3593 enum {
3594 WORD,
c24eb49e 3595 CURLY,
fab56fc5
LP
3596 VARIABLE
3597 } state = WORD;
3598
3599 const char *e, *word = format;
3600 char *r = NULL, *k;
3601
3602 assert(format);
3603
3604 for (e = format; *e; e ++) {
3605
3606 switch (state) {
3607
3608 case WORD:
3609 if (*e == '$')
c24eb49e 3610 state = CURLY;
fab56fc5
LP
3611 break;
3612
c24eb49e
LP
3613 case CURLY:
3614 if (*e == '{') {
fab56fc5
LP
3615 if (!(k = strnappend(r, word, e-word-1)))
3616 goto fail;
3617
3618 free(r);
3619 r = k;
3620
3621 word = e-1;
3622 state = VARIABLE;
3623
3624 } else if (*e == '$') {
3625 if (!(k = strnappend(r, word, e-word)))
3626 goto fail;
3627
3628 free(r);
3629 r = k;
3630
3631 word = e+1;
3632 state = WORD;
3633 } else
3634 state = WORD;
3635 break;
3636
3637 case VARIABLE:
c24eb49e 3638 if (*e == '}') {
b95cf362 3639 const char *t;
fab56fc5 3640
b95cf362
LP
3641 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
3642 t = "";
fab56fc5 3643
b95cf362
LP
3644 if (!(k = strappend(r, t)))
3645 goto fail;
fab56fc5 3646
b95cf362
LP
3647 free(r);
3648 r = k;
fab56fc5 3649
b95cf362 3650 word = e+1;
fab56fc5
LP
3651 state = WORD;
3652 }
3653 break;
3654 }
3655 }
3656
3657 if (!(k = strnappend(r, word, e-word)))
3658 goto fail;
3659
3660 free(r);
3661 return k;
3662
3663fail:
3664 free(r);
3665 return NULL;
3666}
3667
3668char **replace_env_argv(char **argv, char **env) {
3669 char **r, **i;
c24eb49e
LP
3670 unsigned k = 0, l = 0;
3671
3672 l = strv_length(argv);
fab56fc5 3673
c24eb49e 3674 if (!(r = new(char*, l+1)))
fab56fc5
LP
3675 return NULL;
3676
3677 STRV_FOREACH(i, argv) {
c24eb49e
LP
3678
3679 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3680 if ((*i)[0] == '$' && (*i)[1] != '{') {
3681 char *e;
3682 char **w, **m;
3683 unsigned q;
c24eb49e 3684
b95cf362 3685 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
3686
3687 if (!(m = strv_split_quoted(e))) {
3688 r[k] = NULL;
3689 strv_free(r);
3690 return NULL;
3691 }
b95cf362
LP
3692 } else
3693 m = NULL;
c24eb49e 3694
b95cf362
LP
3695 q = strv_length(m);
3696 l = l + q - 1;
c24eb49e 3697
b95cf362
LP
3698 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3699 r[k] = NULL;
3700 strv_free(r);
3701 strv_free(m);
3702 return NULL;
3703 }
c24eb49e 3704
b95cf362
LP
3705 r = w;
3706 if (m) {
c24eb49e
LP
3707 memcpy(r + k, m, q * sizeof(char*));
3708 free(m);
c24eb49e 3709 }
b95cf362
LP
3710
3711 k += q;
3712 continue;
c24eb49e
LP
3713 }
3714
3715 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3716 if (!(r[k++] = replace_env(*i, env))) {
3717 strv_free(r);
3718 return NULL;
3719 }
3720 }
3721
3722 r[k] = NULL;
3723 return r;
3724}
3725
fa776d8e
LP
3726int columns(void) {
3727 static __thread int parsed_columns = 0;
3728 const char *e;
3729
3730 if (parsed_columns > 0)
3731 return parsed_columns;
3732
3733 if ((e = getenv("COLUMNS")))
3734 parsed_columns = atoi(e);
3735
3736 if (parsed_columns <= 0) {
3737 struct winsize ws;
3738 zero(ws);
3739
9ed95f43 3740 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
fa776d8e
LP
3741 parsed_columns = ws.ws_col;
3742 }
3743
3744 if (parsed_columns <= 0)
3745 parsed_columns = 80;
3746
3747 return parsed_columns;
3748}
3749
b4f10a5e
LP
3750int running_in_chroot(void) {
3751 struct stat a, b;
3752
3753 zero(a);
3754 zero(b);
3755
3756 /* Only works as root */
3757
3758 if (stat("/proc/1/root", &a) < 0)
3759 return -errno;
3760
3761 if (stat("/", &b) < 0)
3762 return -errno;
3763
3764 return
3765 a.st_dev != b.st_dev ||
3766 a.st_ino != b.st_ino;
3767}
3768
8fe914ec
LP
3769char *ellipsize(const char *s, unsigned length, unsigned percent) {
3770 size_t l, x;
3771 char *r;
3772
3773 assert(s);
3774 assert(percent <= 100);
3775 assert(length >= 3);
3776
3777 l = strlen(s);
3778
3779 if (l <= 3 || l <= length)
3780 return strdup(s);
3781
3782 if (!(r = new0(char, length+1)))
3783 return r;
3784
3785 x = (length * percent) / 100;
3786
3787 if (x > length - 3)
3788 x = length - 3;
3789
3790 memcpy(r, s, x);
3791 r[x] = '.';
3792 r[x+1] = '.';
3793 r[x+2] = '.';
3794 memcpy(r + x + 3,
3795 s + l - (length - x - 3),
3796 length - x - 3);
3797
3798 return r;
3799}
3800
f6144808
LP
3801int touch(const char *path) {
3802 int fd;
3803
3804 assert(path);
3805
14f3c825 3806 if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644)) < 0)
f6144808
LP
3807 return -errno;
3808
3809 close_nointr_nofail(fd);
3810 return 0;
3811}
afea26ad 3812
97c4a07d 3813char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3814 size_t l;
3815 assert(s);
3816
3817 if ((l = strlen(s)) < 2)
3818 return strdup(s);
3819
97c4a07d 3820 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3821 return strndup(s+1, l-2);
3822
3823 return strdup(s);
3824}
3825
5f7c426e
LP
3826char *normalize_env_assignment(const char *s) {
3827 char *name, *value, *p, *r;
3828
3829 p = strchr(s, '=');
3830
3831 if (!p) {
3832 if (!(r = strdup(s)))
3833 return NULL;
3834
3835 return strstrip(r);
3836 }
3837
3838 if (!(name = strndup(s, p - s)))
3839 return NULL;
3840
3841 if (!(p = strdup(p+1))) {
3842 free(name);
3843 return NULL;
3844 }
3845
3846 value = unquote(strstrip(p), QUOTES);
3847 free(p);
3848
3849 if (!value) {
5f7c426e
LP
3850 free(name);
3851 return NULL;
3852 }
3853
3854 if (asprintf(&r, "%s=%s", name, value) < 0)
3855 r = NULL;
3856
3857 free(value);
3858 free(name);
3859
3860 return r;
3861}
3862
8e12a6ae 3863int wait_for_terminate(pid_t pid, siginfo_t *status) {
2e78aa99
LP
3864 assert(pid >= 1);
3865 assert(status);
3866
3867 for (;;) {
8e12a6ae
LP
3868 zero(*status);
3869
3870 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3871
3872 if (errno == EINTR)
3873 continue;
3874
3875 return -errno;
3876 }
3877
3878 return 0;
3879 }
3880}
3881
97c4a07d
LP
3882int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3883 int r;
3884 siginfo_t status;
3885
3886 assert(name);
3887 assert(pid > 1);
3888
3889 if ((r = wait_for_terminate(pid, &status)) < 0) {
3890 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3891 return r;
3892 }
3893
3894 if (status.si_code == CLD_EXITED) {
3895 if (status.si_status != 0) {
3896 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3897 return status.si_status;
97c4a07d
LP
3898 }
3899
3900 log_debug("%s succeeded.", name);
3901 return 0;
3902
3903 } else if (status.si_code == CLD_KILLED ||
3904 status.si_code == CLD_DUMPED) {
3905
3906 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3907 return -EPROTO;
3908 }
3909
3910 log_warning("%s failed due to unknown reason.", name);
3911 return -EPROTO;
3912
3913}
3914
3c14d26c 3915void freeze(void) {
720ce21d
LP
3916
3917 /* Make sure nobody waits for us on a socket anymore */
3918 close_all_fds(NULL, 0);
3919
c29597a1
LP
3920 sync();
3921
3c14d26c
LP
3922 for (;;)
3923 pause();
3924}
3925
00dc5d76
LP
3926bool null_or_empty(struct stat *st) {
3927 assert(st);
3928
3929 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3930 return true;
3931
c8f26f42 3932 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3933 return true;
3934
3935 return false;
3936}
3937
a247755d 3938DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3939 int nfd;
3940 DIR *d;
3941
3942 if ((nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags)) < 0)
3943 return NULL;
3944
3945 if (!(d = fdopendir(nfd))) {
3946 close_nointr_nofail(nfd);
3947 return NULL;
3948 }
3949
3950 return d;
3b63d2d3
LP
3951}
3952
8a0867d6
LP
3953int signal_from_string_try_harder(const char *s) {
3954 int signo;
3955 assert(s);
3956
3957 if ((signo = signal_from_string(s)) <= 0)
3958 if (startswith(s, "SIG"))
3959 return signal_from_string(s+3);
3960
3961 return signo;
3962}
3963
10717a1a
LP
3964void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
3965
3966 assert(f);
3967 assert(name);
3968 assert(t);
3969
3970 if (!dual_timestamp_is_set(t))
3971 return;
3972
3973 fprintf(f, "%s=%llu %llu\n",
3974 name,
3975 (unsigned long long) t->realtime,
3976 (unsigned long long) t->monotonic);
3977}
3978
799fd0fd 3979void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
10717a1a
LP
3980 unsigned long long a, b;
3981
10717a1a
LP
3982 assert(value);
3983 assert(t);
3984
3985 if (sscanf(value, "%lli %llu", &a, &b) != 2)
3986 log_debug("Failed to parse finish timestamp value %s", value);
3987 else {
3988 t->realtime = a;
3989 t->monotonic = b;
3990 }
3991}
3992
e23a0ce8
LP
3993char *fstab_node_to_udev_node(const char *p) {
3994 char *dn, *t, *u;
3995 int r;
3996
3997 /* FIXME: to follow udev's logic 100% we need to leave valid
3998 * UTF8 chars unescaped */
3999
4000 if (startswith(p, "LABEL=")) {
4001
4002 if (!(u = unquote(p+6, "\"\'")))
4003 return NULL;
4004
4005 t = xescape(u, "/ ");
4006 free(u);
4007
4008 if (!t)
4009 return NULL;
4010
4011 r = asprintf(&dn, "/dev/disk/by-label/%s", t);
4012 free(t);
4013
4014 if (r < 0)
4015 return NULL;
4016
4017 return dn;
4018 }
4019
4020 if (startswith(p, "UUID=")) {
4021
4022 if (!(u = unquote(p+5, "\"\'")))
4023 return NULL;
4024
4025 t = xescape(u, "/ ");
4026 free(u);
4027
4028 if (!t)
4029 return NULL;
4030
0058d7b9 4031 r = asprintf(&dn, "/dev/disk/by-uuid/%s", t);
e23a0ce8
LP
4032 free(t);
4033
4034 if (r < 0)
4035 return NULL;
4036
4037 return dn;
4038 }
4039
4040 return strdup(p);
4041}
4042
e9ddabc2
LP
4043void filter_environ(const char *prefix) {
4044 int i, j;
4045 assert(prefix);
4046
4047 if (!environ)
4048 return;
4049
4050 for (i = 0, j = 0; environ[i]; i++) {
4051
4052 if (startswith(environ[i], prefix))
4053 continue;
4054
4055 environ[j++] = environ[i];
4056 }
4057
4058 environ[j] = NULL;
4059}
4060
f212ac12
LP
4061bool tty_is_vc(const char *tty) {
4062 assert(tty);
4063
4064 if (startswith(tty, "/dev/"))
4065 tty += 5;
4066
98a28fef
LP
4067 return vtnr_from_tty(tty) >= 0;
4068}
4069
4070int vtnr_from_tty(const char *tty) {
4071 int i, r;
4072
4073 assert(tty);
4074
4075 if (startswith(tty, "/dev/"))
4076 tty += 5;
4077
4078 if (!startswith(tty, "tty") )
4079 return -EINVAL;
4080
4081 if (tty[3] < '0' || tty[3] > '9')
4082 return -EINVAL;
4083
4084 r = safe_atoi(tty+3, &i);
4085 if (r < 0)
4086 return r;
4087
4088 if (i < 0 || i > 63)
4089 return -EINVAL;
4090
4091 return i;
f212ac12
LP
4092}
4093
e3aa71c3 4094const char *default_term_for_tty(const char *tty) {
3030ccd7
LP
4095 char *active = NULL;
4096 const char *term;
4097
e3aa71c3
LP
4098 assert(tty);
4099
4100 if (startswith(tty, "/dev/"))
4101 tty += 5;
4102
3030ccd7
LP
4103 /* Resolve where /dev/console is pointing when determining
4104 * TERM */
4105 if (streq(tty, "console"))
4106 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4107 /* If multiple log outputs are configured the
4108 * last one is what /dev/console points to */
4109 if ((tty = strrchr(active, ' ')))
4110 tty++;
4111 else
4112 tty = active;
3030ccd7
LP
4113 }
4114
f212ac12 4115 term = tty_is_vc(tty) ? "TERM=linux" : "TERM=vt100";
3030ccd7 4116 free(active);
e3aa71c3 4117
3030ccd7 4118 return term;
e3aa71c3
LP
4119}
4120
07faed4f
LP
4121/* Returns a short identifier for the various VM implementations */
4122int detect_vm(const char **id) {
46a08e38
LP
4123
4124#if defined(__i386__) || defined(__x86_64__)
4125
4126 /* Both CPUID and DMI are x86 specific interfaces... */
4127
721bca57 4128 static const char *const dmi_vendors[] = {
46a08e38
LP
4129 "/sys/class/dmi/id/sys_vendor",
4130 "/sys/class/dmi/id/board_vendor",
4131 "/sys/class/dmi/id/bios_vendor"
4132 };
4133
4e08da90 4134 static const char dmi_vendor_table[] =
07faed4f
LP
4135 "QEMU\0" "qemu\0"
4136 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
4137 "VMware\0" "vmware\0"
4138 "VMW\0" "vmware\0"
4139 "Microsoft Corporation\0" "microsoft\0"
4140 "innotek GmbH\0" "oracle\0"
4141 "Xen\0" "xen\0"
34df5a34 4142 "Bochs\0" "bochs\0";
07faed4f 4143
4e08da90 4144 static const char cpuid_vendor_table[] =
07faed4f
LP
4145 "XenVMMXenVMM\0" "xen\0"
4146 "KVMKVMKVM\0" "kvm\0"
4147 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
4148 "VMwareVMware\0" "vmware\0"
4149 /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
34df5a34 4150 "Microsoft Hv\0" "microsoft\0";
07faed4f
LP
4151
4152 uint32_t eax, ecx;
46a08e38
LP
4153 union {
4154 uint32_t sig32[3];
4155 char text[13];
4156 } sig;
46a08e38 4157 unsigned i;
07faed4f 4158 const char *j, *k;
721bca57 4159 bool hypervisor;
46a08e38
LP
4160
4161 /* http://lwn.net/Articles/301888/ */
4162 zero(sig);
4163
46a08e38
LP
4164#if defined (__i386__)
4165#define REG_a "eax"
4166#define REG_b "ebx"
4167#elif defined (__amd64__)
4168#define REG_a "rax"
4169#define REG_b "rbx"
4170#endif
4171
07faed4f
LP
4172 /* First detect whether there is a hypervisor */
4173 eax = 1;
46a08e38
LP
4174 __asm__ __volatile__ (
4175 /* ebx/rbx is being used for PIC! */
4176 " push %%"REG_b" \n\t"
4177 " cpuid \n\t"
46a08e38
LP
4178 " pop %%"REG_b" \n\t"
4179
07faed4f 4180 : "=a" (eax), "=c" (ecx)
46a08e38
LP
4181 : "0" (eax)
4182 );
4183
ec195f55 4184 hypervisor = !!(ecx & 0x80000000U);
721bca57
LP
4185
4186 if (hypervisor) {
07faed4f
LP
4187
4188 /* There is a hypervisor, see what it is */
4189 eax = 0x40000000U;
4190 __asm__ __volatile__ (
4191 /* ebx/rbx is being used for PIC! */
4192 " push %%"REG_b" \n\t"
4193 " cpuid \n\t"
4194 " mov %%ebx, %1 \n\t"
4195 " pop %%"REG_b" \n\t"
4196
4197 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
4198 : "0" (eax)
4199 );
4200
4201 NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
4202 if (streq(sig.text, j)) {
4203
4204 if (id)
4205 *id = k;
4206
4207 return 1;
4208 }
721bca57 4209 }
07faed4f 4210
721bca57
LP
4211 for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
4212 char *s;
4213 int r;
4214 const char *found = NULL;
4215
4216 if ((r = read_one_line_file(dmi_vendors[i], &s)) < 0) {
4217 if (r != -ENOENT)
4218 return r;
4219
4220 continue;
4221 }
4222
4223 NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
4224 if (startswith(s, j))
4225 found = k;
4226 free(s);
4227
4228 if (found) {
4229 if (id)
4230 *id = found;
4231
4232 return 1;
4233 }
4234 }
4235
4236 if (hypervisor) {
07faed4f
LP
4237 if (id)
4238 *id = "other";
4239
4240 return 1;
4241 }
46a08e38 4242
721bca57 4243#endif
07faed4f
LP
4244 return 0;
4245}
4246
ef2df9f4 4247int detect_container(const char **id) {
f9b9232b
LP
4248 FILE *f;
4249
ef2df9f4
LP
4250 /* Unfortunately many of these operations require root access
4251 * in one way or another */
f9b9232b 4252
ef2df9f4
LP
4253 if (geteuid() != 0)
4254 return -EPERM;
4255
4256 if (running_in_chroot() > 0) {
f9b9232b
LP
4257
4258 if (id)
ef2df9f4 4259 *id = "chroot";
f9b9232b
LP
4260
4261 return 1;
4262 }
07faed4f 4263
ef2df9f4
LP
4264 /* /proc/vz exists in container and outside of the container,
4265 * /proc/bc only outside of the container. */
4266 if (access("/proc/vz", F_OK) >= 0 &&
4267 access("/proc/bc", F_OK) < 0) {
07faed4f 4268
ef2df9f4
LP
4269 if (id)
4270 *id = "openvz";
4271
4272 return 1;
f9b9232b 4273 }
07faed4f 4274
ccaa6149 4275 if ((f = fopen("/proc/self/cgroup", "re"))) {
f9b9232b
LP
4276
4277 for (;;) {
4278 char line[LINE_MAX], *p;
4279
4280 if (!fgets(line, sizeof(line), f))
4281 break;
4282
4283 if (!(p = strchr(strstrip(line), ':')))
4284 continue;
4285
4286 if (strncmp(p, ":ns:", 4))
4287 continue;
4288
4289 if (!streq(p, ":ns:/")) {
4290 fclose(f);
4291
ef2df9f4 4292 if (id)
28cf382a 4293 *id = "pidns";
ef2df9f4
LP
4294
4295 return 1;
f9b9232b
LP
4296 }
4297 }
4298
4299 fclose(f);
07faed4f
LP
4300 }
4301
ef2df9f4
LP
4302 return 0;
4303}
4304
4305/* Returns a short identifier for the various VM/container implementations */
4306int detect_virtualization(const char **id) {
4307 static __thread const char *cached_id = NULL;
4308 const char *_id;
4309 int r;
4310
4311 if (cached_id) {
4312
4313 if (cached_id == (const char*) -1)
4314 return 0;
4315
4316 if (id)
4317 *id = cached_id;
4318
4319 return 1;
f9b9232b 4320 }
07faed4f 4321
ef2df9f4
LP
4322 if ((r = detect_container(&_id)) != 0)
4323 goto finish;
4324
f9b9232b 4325 r = detect_vm(&_id);
07faed4f 4326
f9b9232b 4327finish:
ef2df9f4 4328 if (r > 0) {
f9b9232b 4329 cached_id = _id;
07faed4f 4330
ef2df9f4
LP
4331 if (id)
4332 *id = _id;
4333 } else if (r == 0)
4334 cached_id = (const char*) -1;
f9b9232b
LP
4335
4336 return r;
46a08e38
LP
4337}
4338
fb19a739
LP
4339bool dirent_is_file(struct dirent *de) {
4340 assert(de);
4341
4342 if (ignore_file(de->d_name))
4343 return false;
4344
4345 if (de->d_type != DT_REG &&
4346 de->d_type != DT_LNK &&
4347 de->d_type != DT_UNKNOWN)
4348 return false;
4349
4350 return true;
4351}
4352
83cc030f
LP
4353void execute_directory(const char *directory, DIR *d, char *argv[]) {
4354 DIR *_d = NULL;
4355 struct dirent *de;
4356 Hashmap *pids = NULL;
4357
4358 assert(directory);
4359
4360 /* Executes all binaries in a directory in parallel and waits
4361 * until all they all finished. */
4362
4363 if (!d) {
4364 if (!(_d = opendir(directory))) {
4365
4366 if (errno == ENOENT)
4367 return;
4368
4369 log_error("Failed to enumerate directory %s: %m", directory);
4370 return;
4371 }
4372
4373 d = _d;
4374 }
4375
4376 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4377 log_error("Failed to allocate set.");
4378 goto finish;
4379 }
4380
4381 while ((de = readdir(d))) {
4382 char *path;
4383 pid_t pid;
4384 int k;
4385
fb19a739 4386 if (!dirent_is_file(de))
83cc030f
LP
4387 continue;
4388
4389 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
4390 log_error("Out of memory");
4391 continue;
4392 }
4393
4394 if ((pid = fork()) < 0) {
4395 log_error("Failed to fork: %m");
4396 free(path);
4397 continue;
4398 }
4399
4400 if (pid == 0) {
4401 char *_argv[2];
4402 /* Child */
4403
4404 if (!argv) {
4405 _argv[0] = path;
4406 _argv[1] = NULL;
4407 argv = _argv;
4408 } else
4409 if (!argv[0])
4410 argv[0] = path;
4411
4412 execv(path, argv);
4413
4414 log_error("Failed to execute %s: %m", path);
4415 _exit(EXIT_FAILURE);
4416 }
4417
4418 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4419
4420 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4421 log_error("Failed to add PID to set: %s", strerror(-k));
4422 free(path);
4423 }
4424 }
4425
4426 while (!hashmap_isempty(pids)) {
4427 siginfo_t si;
4428 char *path;
4429
4430 zero(si);
4431 if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
4432
4433 if (errno == EINTR)
4434 continue;
4435
4436 log_error("waitid() failed: %m");
4437 goto finish;
4438 }
4439
4440 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
4441 if (!is_clean_exit(si.si_code, si.si_status)) {
4442 if (si.si_code == CLD_EXITED)
4443 log_error("%s exited with exit status %i.", path, si.si_status);
4444 else
4445 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4446 } else
4447 log_debug("%s exited successfully.", path);
4448
4449 free(path);
4450 }
4451 }
4452
4453finish:
4454 if (_d)
4455 closedir(_d);
4456
4457 if (pids)
4458 hashmap_free_free(pids);
4459}
4460
430c18ed
LP
4461int kill_and_sigcont(pid_t pid, int sig) {
4462 int r;
4463
4464 r = kill(pid, sig) < 0 ? -errno : 0;
4465
4466 if (r >= 0)
4467 kill(pid, SIGCONT);
4468
4469 return r;
4470}
4471
05feefe0
LP
4472bool nulstr_contains(const char*nulstr, const char *needle) {
4473 const char *i;
4474
4475 if (!nulstr)
4476 return false;
4477
4478 NULSTR_FOREACH(i, nulstr)
4479 if (streq(i, needle))
4480 return true;
4481
4482 return false;
4483}
4484
6faa1114 4485bool plymouth_running(void) {
9408a2d2 4486 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4487}
4488
7c3b203c
LP
4489void parse_syslog_priority(char **p, int *priority) {
4490 int a = 0, b = 0, c = 0;
4491 int k;
4492
4493 assert(p);
4494 assert(*p);
4495 assert(priority);
4496
4497 if ((*p)[0] != '<')
4498 return;
4499
4500 if (!strchr(*p, '>'))
4501 return;
4502
4503 if ((*p)[2] == '>') {
4504 c = undecchar((*p)[1]);
4505 k = 3;
4506 } else if ((*p)[3] == '>') {
4507 b = undecchar((*p)[1]);
4508 c = undecchar((*p)[2]);
4509 k = 4;
4510 } else if ((*p)[4] == '>') {
4511 a = undecchar((*p)[1]);
4512 b = undecchar((*p)[2]);
4513 c = undecchar((*p)[3]);
4514 k = 5;
4515 } else
4516 return;
4517
4518 if (a < 0 || b < 0 || c < 0)
4519 return;
4520
4521 *priority = a*100+b*10+c;
4522 *p += k;
4523}
4524
ac123445
LP
4525int have_effective_cap(int value) {
4526 cap_t cap;
4527 cap_flag_value_t fv;
4528 int r;
4529
4530 if (!(cap = cap_get_proc()))
4531 return -errno;
4532
4533 if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
4534 r = -errno;
4535 else
4536 r = fv == CAP_SET;
4537
4538 cap_free(cap);
4539 return r;
4540}
4541
9beb3f4d
LP
4542char* strshorten(char *s, size_t l) {
4543 assert(s);
4544
4545 if (l < strlen(s))
4546 s[l] = 0;
4547
4548 return s;
4549}
4550
4551static bool hostname_valid_char(char c) {
4552 return
4553 (c >= 'a' && c <= 'z') ||
4554 (c >= 'A' && c <= 'Z') ||
4555 (c >= '0' && c <= '9') ||
4556 c == '-' ||
4557 c == '_' ||
4558 c == '.';
4559}
4560
4561bool hostname_is_valid(const char *s) {
4562 const char *p;
4563
4564 if (isempty(s))
4565 return false;
4566
4567 for (p = s; *p; p++)
4568 if (!hostname_valid_char(*p))
4569 return false;
4570
4571 if (p-s > HOST_NAME_MAX)
4572 return false;
4573
4574 return true;
4575}
4576
4577char* hostname_cleanup(char *s) {
4578 char *p, *d;
4579
4580 for (p = s, d = s; *p; p++)
4581 if ((*p >= 'a' && *p <= 'z') ||
4582 (*p >= 'A' && *p <= 'Z') ||
4583 (*p >= '0' && *p <= '9') ||
4584 *p == '-' ||
4585 *p == '_' ||
4586 *p == '.')
4587 *(d++) = *p;
4588
4589 *d = 0;
4590
4591 strshorten(s, HOST_NAME_MAX);
4592 return s;
4593}
4594
1325aa42
LP
4595int pipe_eof(int fd) {
4596 struct pollfd pollfd;
4597 int r;
4598
4599 zero(pollfd);
4600 pollfd.fd = fd;
4601 pollfd.events = POLLIN|POLLHUP;
4602
4603 r = poll(&pollfd, 1, 0);
4604 if (r < 0)
4605 return -errno;
4606
4607 if (r == 0)
4608 return 0;
4609
4610 return pollfd.revents & POLLHUP;
4611}
4612
5a3ab509
LP
4613int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4614 FILE *f;
4615 char *t;
4616 const char *fn;
4617 size_t k;
4618 int fd;
4619
4620 assert(path);
4621 assert(_f);
4622 assert(_temp_path);
4623
4624 t = new(char, strlen(path) + 1 + 6 + 1);
4625 if (!t)
4626 return -ENOMEM;
4627
4628 fn = file_name_from_path(path);
4629 k = fn-path;
4630 memcpy(t, path, k);
4631 t[k] = '.';
4632 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4633
4634 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4635 if (fd < 0) {
4636 free(t);
4637 return -errno;
4638 }
4639
4640 f = fdopen(fd, "we");
4641 if (!f) {
4642 unlink(t);
4643 free(t);
4644 return -errno;
4645 }
4646
4647 *_f = f;
4648 *_temp_path = t;
4649
4650 return 0;
4651}
4652
6ea832a2 4653int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4654 assert(fd >= 0);
4655
6ea832a2
LP
4656 if (ioctl(fd, TIOCVHANGUP) < 0)
4657 return -errno;
4658
4659 return 0;
4660}
4661
4662int terminal_vhangup(const char *name) {
4663 int fd, r;
4664
4665 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4666 if (fd < 0)
4667 return fd;
4668
4669 r = terminal_vhangup_fd(fd);
4670 close_nointr_nofail(fd);
4671
4672 return r;
4673}
4674
4675int vt_disallocate(const char *name) {
4676 int fd, r;
4677 unsigned u;
6ea832a2
LP
4678
4679 /* Deallocate the VT if possible. If not possible
4680 * (i.e. because it is the active one), at least clear it
4681 * entirely (including the scrollback buffer) */
4682
b83bc4e9
LP
4683 if (!startswith(name, "/dev/"))
4684 return -EINVAL;
4685
4686 if (!tty_is_vc(name)) {
4687 /* So this is not a VT. I guess we cannot deallocate
4688 * it then. But let's at least clear the screen */
4689
4690 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4691 if (fd < 0)
4692 return fd;
4693
8585357a
LP
4694 loop_write(fd,
4695 "\033[r" /* clear scrolling region */
4696 "\033[H" /* move home */
4697 "\033[2J", /* clear screen */
4698 10, false);
b83bc4e9
LP
4699 close_nointr_nofail(fd);
4700
4701 return 0;
4702 }
6ea832a2
LP
4703
4704 if (!startswith(name, "/dev/tty"))
4705 return -EINVAL;
4706
4707 r = safe_atou(name+8, &u);
4708 if (r < 0)
4709 return r;
4710
4711 if (u <= 0)
b83bc4e9 4712 return -EINVAL;
6ea832a2 4713
b83bc4e9 4714 /* Try to deallocate */
6ea832a2
LP
4715 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4716 if (fd < 0)
4717 return fd;
4718
4719 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4720 close_nointr_nofail(fd);
6ea832a2 4721
b83bc4e9
LP
4722 if (r >= 0)
4723 return 0;
6ea832a2 4724
b83bc4e9 4725 if (errno != EBUSY)
6ea832a2 4726 return -errno;
6ea832a2 4727
b83bc4e9
LP
4728 /* Couldn't deallocate, so let's clear it fully with
4729 * scrollback */
4730 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4731 if (fd < 0)
b83bc4e9 4732 return fd;
6ea832a2 4733
8585357a
LP
4734 loop_write(fd,
4735 "\033[r" /* clear scrolling region */
4736 "\033[H" /* move home */
4737 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4738 10, false);
b83bc4e9 4739 close_nointr_nofail(fd);
6ea832a2 4740
b83bc4e9 4741 return 0;
6ea832a2
LP
4742}
4743
db1413d7
KS
4744
4745static int file_is_conf(const struct dirent *d, const char *suffix) {
4746 assert(d);
4747
4748 if (ignore_file(d->d_name))
4749 return 0;
4750
4751 if (d->d_type != DT_REG &&
4752 d->d_type != DT_LNK &&
4753 d->d_type != DT_UNKNOWN)
4754 return 0;
4755
4756 return endswith(d->d_name, suffix);
4757}
4758
4759static int files_add(Hashmap *h, const char *path, const char *suffix) {
4760 DIR *dir;
4761 struct dirent *de;
4762 int r = 0;
4763
4764 dir = opendir(path);
4765 if (!dir) {
4766 if (errno == ENOENT)
4767 return 0;
4768 return -errno;
4769 }
4770
4771 for (de = readdir(dir); de; de = readdir(dir)) {
223a3558 4772 char *p, *f;
db1413d7
KS
4773 const char *base;
4774
4775 if (!file_is_conf(de, suffix))
4776 continue;
4777
223a3558 4778 if (asprintf(&p, "%s/%s", path, de->d_name) < 0) {
db1413d7
KS
4779 r = -ENOMEM;
4780 goto finish;
4781 }
4782
223a3558
KS
4783 f = canonicalize_file_name(p);
4784 if (!f) {
4785 log_error("Failed to canonicalize file name '%s': %m", p);
4786 free(p);
4787 continue;
4788 }
4789 free(p);
4790
db1413d7
KS
4791 log_debug("found: %s\n", f);
4792 base = f + strlen(path) + 1;
4793 if (hashmap_put(h, base, f) <= 0)
4794 free(f);
4795 }
4796
4797finish:
4798 closedir(dir);
4799 return r;
4800}
4801
4802static int base_cmp(const void *a, const void *b) {
4803 const char *s1, *s2;
4804
4805 s1 = *(char * const *)a;
4806 s2 = *(char * const *)b;
4807 return strcmp(file_name_from_path(s1), file_name_from_path(s2));
4808}
4809
44143309 4810int conf_files_list(char ***strv, const char *suffix, const char *dir, ...) {
223a3558
KS
4811 Hashmap *fh = NULL;
4812 char **dirs = NULL;
db1413d7 4813 char **files = NULL;
223a3558 4814 char **p;
db1413d7 4815 va_list ap;
44143309 4816 int r = 0;
db1413d7 4817
223a3558
KS
4818 va_start(ap, dir);
4819 dirs = strv_new_ap(dir, ap);
4820 va_end(ap);
4821 if (!dirs) {
4822 r = -ENOMEM;
4823 goto finish;
4824 }
4825 if (!strv_path_canonicalize(dirs)) {
4826 r = -ENOMEM;
4827 goto finish;
4828 }
4829 if (!strv_uniq(dirs)) {
4830 r = -ENOMEM;
4831 goto finish;
4832 }
4833
db1413d7
KS
4834 fh = hashmap_new(string_hash_func, string_compare_func);
4835 if (!fh) {
44143309 4836 r = -ENOMEM;
db1413d7
KS
4837 goto finish;
4838 }
4839
223a3558
KS
4840 STRV_FOREACH(p, dirs) {
4841 if (files_add(fh, *p, suffix) < 0) {
db1413d7 4842 log_error("Failed to search for files.");
44143309 4843 r = -EINVAL;
db1413d7
KS
4844 goto finish;
4845 }
db1413d7 4846 }
db1413d7
KS
4847
4848 files = hashmap_get_strv(fh);
4849 if (files == NULL) {
4850 log_error("Failed to compose list of files.");
44143309 4851 r = -ENOMEM;
db1413d7
KS
4852 goto finish;
4853 }
4854
4855 qsort(files, hashmap_size(fh), sizeof(char *), base_cmp);
8d0e38a2 4856
db1413d7 4857finish:
223a3558 4858 strv_free(dirs);
db1413d7 4859 hashmap_free(fh);
44143309
KS
4860 *strv = files;
4861 return r;
db1413d7 4862}
7948c4df 4863
2076cf88 4864int hwclock_is_localtime(void) {
7948c4df 4865 FILE *f;
7948c4df
KS
4866 bool local = false;
4867
4868 /*
4869 * The third line of adjtime is "UTC" or "LOCAL" or nothing.
4870 * # /etc/adjtime
2076cf88 4871 * 0.0 0 0
7948c4df
KS
4872 * 0
4873 * UTC
4874 */
4875 f = fopen("/etc/adjtime", "re");
4876 if (f) {
2076cf88
LP
4877 char line[LINE_MAX];
4878 bool b;
4879
4880 b = fgets(line, sizeof(line), f) &&
4881 fgets(line, sizeof(line), f) &&
4882 fgets(line, sizeof(line), f);
4883
7948c4df 4884 fclose(f);
2076cf88
LP
4885
4886 if (!b)
4887 return -EIO;
4888
4889
4890 truncate_nl(line);
4891 local = streq(line, "LOCAL");
4892
4893 } else if (errno != -ENOENT)
4894 return -errno;
4895
7948c4df
KS
4896 return local;
4897}
4898
4899int hwclock_apply_localtime_delta(void) {
4900 const struct timeval *tv_null = NULL;
2076cf88 4901 struct timespec ts;
7948c4df
KS
4902 struct tm *tm;
4903 int minuteswest;
4904 struct timezone tz;
4905
2076cf88
LP
4906 assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
4907 assert_se(tm = localtime(&ts.tv_sec));
7948c4df
KS
4908 minuteswest = tm->tm_gmtoff / 60;
4909
4910 tz.tz_minuteswest = -minuteswest;
4911 tz.tz_dsttime = 0; /* DST_NONE*/
4912
4913 /*
4914 * If the hardware clock does not run in UTC, but in local time:
4915 * The very first time we set the kernel's timezone, it will warp
4916 * the clock so that it runs in UTC instead of local time.
4917 */
4918 if (settimeofday(tv_null, &tz) < 0)
4919 return -errno;
2076cf88
LP
4920
4921 return minuteswest;
4922}
4923
4924int hwclock_reset_localtime_delta(void) {
4925 const struct timeval *tv_null = NULL;
4926 struct timezone tz;
4927
4928 tz.tz_minuteswest = 0;
4929 tz.tz_dsttime = 0; /* DST_NONE*/
4930
4931 if (settimeofday(tv_null, &tz) < 0)
4932 return -errno;
4933
4934 return 0;
7948c4df
KS
4935}
4936
4937int hwclock_get_time(struct tm *tm) {
4938 int fd;
4939 int err = 0;
4940
2076cf88
LP
4941 assert(tm);
4942
7948c4df
KS
4943 fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
4944 if (fd < 0)
4945 return -errno;
2076cf88
LP
4946
4947 /* This leaves the timezone fields of struct tm
4948 * uninitialized! */
7948c4df
KS
4949 if (ioctl(fd, RTC_RD_TIME, tm) < 0)
4950 err = -errno;
2076cf88
LP
4951
4952 /* We don't now daylight saving, so we reset this in order not
4953 * to confused mktime(). */
4954 tm->tm_isdst = -1;
4955
4956 close_nointr_nofail(fd);
7948c4df
KS
4957
4958 return err;
4959}
4960
4961int hwclock_set_time(const struct tm *tm) {
4962 int fd;
4963 int err = 0;
4964
2076cf88
LP
4965 assert(tm);
4966
7948c4df
KS
4967 fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
4968 if (fd < 0)
4969 return -errno;
2076cf88 4970
7948c4df
KS
4971 if (ioctl(fd, RTC_SET_TIME, tm) < 0)
4972 err = -errno;
2076cf88
LP
4973
4974 close_nointr_nofail(fd);
7948c4df
KS
4975
4976 return err;
4977}
f41607a6 4978
34ca941c
LP
4979int copy_file(const char *from, const char *to) {
4980 int r, fdf, fdt;
4981
4982 assert(from);
4983 assert(to);
4984
4985 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4986 if (fdf < 0)
4987 return -errno;
4988
4989 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4990 if (fdt < 0) {
4991 close_nointr_nofail(fdf);
4992 return -errno;
4993 }
4994
4995 for (;;) {
4996 char buf[PIPE_BUF];
4997 ssize_t n, k;
4998
4999 n = read(fdf, buf, sizeof(buf));
5000 if (n < 0) {
5001 r = -errno;
5002
5003 close_nointr_nofail(fdf);
5004 close_nointr(fdt);
5005 unlink(to);
5006
5007 return r;
5008 }
5009
5010 if (n == 0)
5011 break;
5012
5013 errno = 0;
5014 k = loop_write(fdt, buf, n, false);
5015 if (n != k) {
5016 r = k < 0 ? k : (errno ? -errno : -EIO);
5017
5018 close_nointr_nofail(fdf);
5019 close_nointr(fdt);
5020
5021 unlink(to);
5022 return r;
5023 }
5024 }
5025
5026 close_nointr_nofail(fdf);
5027 r = close_nointr(fdt);
5028
5029 if (r < 0) {
5030 unlink(to);
5031 return r;
5032 }
5033
5034 return 0;
5035}
5036
5037int symlink_or_copy(const char *from, const char *to) {
5038 char *pf = NULL, *pt = NULL;
5039 struct stat a, b;
5040 int r;
5041
5042 assert(from);
5043 assert(to);
5044
5045 if (parent_of_path(from, &pf) < 0 ||
5046 parent_of_path(to, &pt) < 0) {
5047 r = -ENOMEM;
5048 goto finish;
5049 }
5050
5051 if (stat(pf, &a) < 0 ||
5052 stat(pt, &b) < 0) {
5053 r = -errno;
5054 goto finish;
5055 }
5056
5057 if (a.st_dev != b.st_dev) {
5058 free(pf);
5059 free(pt);
5060
5061 return copy_file(from, to);
5062 }
5063
5064 if (symlink(from, to) < 0) {
5065 r = -errno;
5066 goto finish;
5067 }
5068
5069 r = 0;
5070
5071finish:
5072 free(pf);
5073 free(pt);
5074
5075 return r;
5076}
5077
5078int symlink_or_copy_atomic(const char *from, const char *to) {
5079 char *t, *x;
5080 const char *fn;
5081 size_t k;
5082 unsigned long long ull;
5083 unsigned i;
5084 int r;
5085
5086 assert(from);
5087 assert(to);
5088
5089 t = new(char, strlen(to) + 1 + 16 + 1);
5090 if (!t)
5091 return -ENOMEM;
5092
5093 fn = file_name_from_path(to);
5094 k = fn-to;
5095 memcpy(t, to, k);
5096 t[k] = '.';
5097 x = stpcpy(t+k+1, fn);
5098
5099 ull = random_ull();
5100 for (i = 0; i < 16; i++) {
5101 *(x++) = hexchar(ull & 0xF);
5102 ull >>= 4;
5103 }
5104
5105 *x = 0;
5106
5107 r = symlink_or_copy(from, t);
5108 if (r < 0) {
5109 unlink(t);
5110 free(t);
5111 return r;
5112 }
5113
5114 if (rename(t, to) < 0) {
5115 r = -errno;
5116 unlink(t);
5117 free(t);
5118 return r;
5119 }
5120
5121 free(t);
5122 return r;
5123}
5124
98a28fef
LP
5125int audit_session_from_pid(pid_t pid, uint32_t *id) {
5126 char *p, *s;
5127 uint32_t u;
5128 int r;
5129
5130 assert(pid >= 1);
5131 assert(id);
5132
5133 if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
5134 return -ENOENT;
5135
5136 if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
5137 return -ENOMEM;
5138
5139 r = read_one_line_file(p, &s);
5140 free(p);
5141 if (r < 0)
5142 return r;
5143
5144 r = safe_atou32(s, &u);
5145 free(s);
5146
5147 if (r < 0)
5148 return r;
5149
5150 if (u == (uint32_t) -1 || u <= 0)
5151 return -ENOENT;
5152
5153 *id = u;
5154 return 0;
5155}
5156
4d6d6518
LP
5157bool display_is_local(const char *display) {
5158 assert(display);
5159
5160 return
5161 display[0] == ':' &&
5162 display[1] >= '0' &&
5163 display[1] <= '9';
5164}
5165
5166int socket_from_display(const char *display, char **path) {
5167 size_t k;
5168 char *f, *c;
5169
5170 assert(display);
5171 assert(path);
5172
5173 if (!display_is_local(display))
5174 return -EINVAL;
5175
5176 k = strspn(display+1, "0123456789");
5177
5178 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
5179 if (!f)
5180 return -ENOMEM;
5181
5182 c = stpcpy(f, "/tmp/.X11-unix/X");
5183 memcpy(c, display+1, k);
5184 c[k] = 0;
5185
5186 *path = f;
5187
5188 return 0;
5189}
5190
1cccf435
MV
5191int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
5192 struct passwd *p;
5193 unsigned long lu;
5194
5195 assert(username);
5196 assert(*username);
5197 assert(uid);
5198 assert(gid);
5199 assert(home);
5200
5201 /* We enforce some special rules for uid=0: in order to avoid
5202 * NSS lookups for root we hardcode its data. */
5203
5204 if (streq(*username, "root") || streq(*username, "0")) {
5205 *username = "root";
5206 *uid = 0;
5207 *gid = 0;
5208 *home = "/root";
5209 return 0;
5210 }
5211
5212 if (safe_atolu(*username, &lu) >= 0) {
5213 errno = 0;
5214 p = getpwuid((uid_t) lu);
5215
5216 /* If there are multiple users with the same id, make
5217 * sure to leave $USER to the configured value instead
5218 * of the first occurrence in the database. However if
5219 * the uid was configured by a numeric uid, then let's
5220 * pick the real username from /etc/passwd. */
5221 if (p)
5222 *username = p->pw_name;
5223 } else {
5224 errno = 0;
5225 p = getpwnam(*username);
5226 }
5227
5228 if (!p)
5229 return errno != 0 ? -errno : -ESRCH;
5230
5231 *uid = p->pw_uid;
5232 *gid = p->pw_gid;
5233 *home = p->pw_dir;
5234 return 0;
5235}
5236
f41607a6
LP
5237static const char *const ioprio_class_table[] = {
5238 [IOPRIO_CLASS_NONE] = "none",
5239 [IOPRIO_CLASS_RT] = "realtime",
5240 [IOPRIO_CLASS_BE] = "best-effort",
5241 [IOPRIO_CLASS_IDLE] = "idle"
5242};
5243
5244DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5245
5246static const char *const sigchld_code_table[] = {
5247 [CLD_EXITED] = "exited",
5248 [CLD_KILLED] = "killed",
5249 [CLD_DUMPED] = "dumped",
5250 [CLD_TRAPPED] = "trapped",
5251 [CLD_STOPPED] = "stopped",
5252 [CLD_CONTINUED] = "continued",
5253};
5254
5255DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5256
5257static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5258 [LOG_FAC(LOG_KERN)] = "kern",
5259 [LOG_FAC(LOG_USER)] = "user",
5260 [LOG_FAC(LOG_MAIL)] = "mail",
5261 [LOG_FAC(LOG_DAEMON)] = "daemon",
5262 [LOG_FAC(LOG_AUTH)] = "auth",
5263 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5264 [LOG_FAC(LOG_LPR)] = "lpr",
5265 [LOG_FAC(LOG_NEWS)] = "news",
5266 [LOG_FAC(LOG_UUCP)] = "uucp",
5267 [LOG_FAC(LOG_CRON)] = "cron",
5268 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5269 [LOG_FAC(LOG_FTP)] = "ftp",
5270 [LOG_FAC(LOG_LOCAL0)] = "local0",
5271 [LOG_FAC(LOG_LOCAL1)] = "local1",
5272 [LOG_FAC(LOG_LOCAL2)] = "local2",
5273 [LOG_FAC(LOG_LOCAL3)] = "local3",
5274 [LOG_FAC(LOG_LOCAL4)] = "local4",
5275 [LOG_FAC(LOG_LOCAL5)] = "local5",
5276 [LOG_FAC(LOG_LOCAL6)] = "local6",
5277 [LOG_FAC(LOG_LOCAL7)] = "local7"
5278};
5279
5280DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5281
5282static const char *const log_level_table[] = {
5283 [LOG_EMERG] = "emerg",
5284 [LOG_ALERT] = "alert",
5285 [LOG_CRIT] = "crit",
5286 [LOG_ERR] = "err",
5287 [LOG_WARNING] = "warning",
5288 [LOG_NOTICE] = "notice",
5289 [LOG_INFO] = "info",
5290 [LOG_DEBUG] = "debug"
5291};
5292
5293DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5294
5295static const char* const sched_policy_table[] = {
5296 [SCHED_OTHER] = "other",
5297 [SCHED_BATCH] = "batch",
5298 [SCHED_IDLE] = "idle",
5299 [SCHED_FIFO] = "fifo",
5300 [SCHED_RR] = "rr"
5301};
5302
5303DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5304
5305static const char* const rlimit_table[] = {
5306 [RLIMIT_CPU] = "LimitCPU",
5307 [RLIMIT_FSIZE] = "LimitFSIZE",
5308 [RLIMIT_DATA] = "LimitDATA",
5309 [RLIMIT_STACK] = "LimitSTACK",
5310 [RLIMIT_CORE] = "LimitCORE",
5311 [RLIMIT_RSS] = "LimitRSS",
5312 [RLIMIT_NOFILE] = "LimitNOFILE",
5313 [RLIMIT_AS] = "LimitAS",
5314 [RLIMIT_NPROC] = "LimitNPROC",
5315 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5316 [RLIMIT_LOCKS] = "LimitLOCKS",
5317 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5318 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5319 [RLIMIT_NICE] = "LimitNICE",
5320 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5321 [RLIMIT_RTTIME] = "LimitRTTIME"
5322};
5323
5324DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5325
5326static const char* const ip_tos_table[] = {
5327 [IPTOS_LOWDELAY] = "low-delay",
5328 [IPTOS_THROUGHPUT] = "throughput",
5329 [IPTOS_RELIABILITY] = "reliability",
5330 [IPTOS_LOWCOST] = "low-cost",
5331};
5332
5333DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5334
5335static const char *const signal_table[] = {
5336 [SIGHUP] = "HUP",
5337 [SIGINT] = "INT",
5338 [SIGQUIT] = "QUIT",
5339 [SIGILL] = "ILL",
5340 [SIGTRAP] = "TRAP",
5341 [SIGABRT] = "ABRT",
5342 [SIGBUS] = "BUS",
5343 [SIGFPE] = "FPE",
5344 [SIGKILL] = "KILL",
5345 [SIGUSR1] = "USR1",
5346 [SIGSEGV] = "SEGV",
5347 [SIGUSR2] = "USR2",
5348 [SIGPIPE] = "PIPE",
5349 [SIGALRM] = "ALRM",
5350 [SIGTERM] = "TERM",
5351#ifdef SIGSTKFLT
5352 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5353#endif
5354 [SIGCHLD] = "CHLD",
5355 [SIGCONT] = "CONT",
5356 [SIGSTOP] = "STOP",
5357 [SIGTSTP] = "TSTP",
5358 [SIGTTIN] = "TTIN",
5359 [SIGTTOU] = "TTOU",
5360 [SIGURG] = "URG",
5361 [SIGXCPU] = "XCPU",
5362 [SIGXFSZ] = "XFSZ",
5363 [SIGVTALRM] = "VTALRM",
5364 [SIGPROF] = "PROF",
5365 [SIGWINCH] = "WINCH",
5366 [SIGIO] = "IO",
5367 [SIGPWR] = "PWR",
5368 [SIGSYS] = "SYS"
5369};
5370
5371DEFINE_STRING_TABLE_LOOKUP(signal, int);