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