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