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