]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
main: rename a few fix to follow general naming style
[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
3149 * tries to go on */
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;
ad293f5a 3160 bool is_dir, keep_around = false;
8c6db833
LP
3161 int r;
3162
d4d046e3
LP
3163 r = readdir_r(d, &buf, &de);
3164 if (r != 0 && ret == 0) {
3165 ret = -r;
8c6db833
LP
3166 break;
3167 }
3168
3169 if (!de)
3170 break;
3171
3172 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
3173 continue;
3174
3175 if (de->d_type == DT_UNKNOWN) {
3176 struct stat st;
3177
3178 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 3179 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3180 ret = -errno;
3181 continue;
3182 }
3183
ad293f5a 3184 if (honour_sticky)
8d53b453
LP
3185 keep_around =
3186 (st.st_uid == 0 || st.st_uid == getuid()) &&
3187 (st.st_mode & S_ISVTX);
ad293f5a 3188
8c6db833 3189 is_dir = S_ISDIR(st.st_mode);
ad293f5a
LP
3190
3191 } else {
3192 if (honour_sticky) {
3193 struct stat st;
3194
3195 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
3196 if (ret == 0 && errno != ENOENT)
3197 ret = -errno;
3198 continue;
3199 }
3200
8d53b453
LP
3201 keep_around =
3202 (st.st_uid == 0 || st.st_uid == getuid()) &&
3203 (st.st_mode & S_ISVTX);
ad293f5a
LP
3204 }
3205
8c6db833 3206 is_dir = de->d_type == DT_DIR;
ad293f5a 3207 }
8c6db833
LP
3208
3209 if (is_dir) {
3210 int subdir_fd;
597f43c7
HH
3211 struct stat sb;
3212 if (root_dev) {
3213 if (fstatat(fd, de->d_name, &sb, AT_SYMLINK_NOFOLLOW)) {
3214 if (ret == 0 && errno != ENOENT)
3215 ret = -errno;
3216 continue;
3217 }
8c6db833
LP
3218 }
3219
597f43c7
HH
3220 /* if root_dev is set, remove subdirectories only, if device is same as dir */
3221 if ((root_dev == NULL) || (sb.st_dev == root_dev->st_dev)) {
8c6db833 3222
597f43c7
HH
3223 subdir_fd = openat(fd, de->d_name,
3224 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3225 if (subdir_fd < 0) {
ad293f5a
LP
3226 if (ret == 0 && errno != ENOENT)
3227 ret = -errno;
597f43c7 3228 continue;
ad293f5a
LP
3229 }
3230
597f43c7
HH
3231 r = rm_rf_children(subdir_fd, only_dirs, honour_sticky, root_dev);
3232 if (r < 0 && ret == 0)
3233 ret = r;
3234
3235 if (!keep_around)
3236 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
3237 if (ret == 0 && errno != ENOENT)
3238 ret = -errno;
3239 }
3240 }
3241
ad293f5a 3242 } else if (!only_dirs && !keep_around) {
8c6db833
LP
3243
3244 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 3245 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3246 ret = -errno;
3247 }
3248 }
3249 }
3250
3251 closedir(d);
3252
3253 return ret;
3254}
3255
ad293f5a 3256int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
8c6db833
LP
3257 int fd;
3258 int r;
3259
3260 assert(path);
3261
d4d046e3
LP
3262 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3263 if (fd < 0) {
8c6db833
LP
3264
3265 if (errno != ENOTDIR)
3266 return -errno;
3267
3268 if (delete_root && !only_dirs)
d4d046e3 3269 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
3270 return -errno;
3271
3272 return 0;
3273 }
3274
597f43c7 3275 r = rm_rf_children(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
3276
3277 if (delete_root) {
3278
8d53b453 3279 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 3280 return r;
8c6db833 3281
e27796a0 3282 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
3283 if (r == 0)
3284 r = -errno;
3285 }
ad293f5a 3286 }
8c6db833
LP
3287
3288 return r;
3289}
3290
3291int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
3292 assert(path);
3293
3294 /* Under the assumption that we are running privileged we
3295 * first change the access mode and only then hand out
3296 * ownership to avoid a window where access is too open. */
3297
8d53b453
LP
3298 if (mode != (mode_t) -1)
3299 if (chmod(path, mode) < 0)
3300 return -errno;
8c6db833 3301
8d53b453
LP
3302 if (uid != (uid_t) -1 || gid != (gid_t) -1)
3303 if (chown(path, uid, gid) < 0)
3304 return -errno;
8c6db833
LP
3305
3306 return 0;
ef2f1067
LP
3307}
3308
f4b47811
LP
3309int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
3310 assert(fd >= 0);
3311
3312 /* Under the assumption that we are running privileged we
3313 * first change the access mode and only then hand out
3314 * ownership to avoid a window where access is too open. */
3315
3316 if (fchmod(fd, mode) < 0)
3317 return -errno;
3318
3319 if (fchown(fd, uid, gid) < 0)
3320 return -errno;
3321
3322 return 0;
3323}
3324
82c121a4
LP
3325cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
3326 cpu_set_t *r;
3327 unsigned n = 1024;
3328
3329 /* Allocates the cpuset in the right size */
3330
3331 for (;;) {
3332 if (!(r = CPU_ALLOC(n)))
3333 return NULL;
3334
3335 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
3336 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
3337
3338 if (ncpus)
3339 *ncpus = n;
3340
3341 return r;
3342 }
3343
3344 CPU_FREE(r);
3345
3346 if (errno != EINVAL)
3347 return NULL;
3348
3349 n *= 2;
3350 }
3351}
3352
67e5cc4f 3353void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
9ab7a8d2
MS
3354 char *s = NULL;
3355 static const char status_indent[] = " "; /* "[" STATUS "] " */
3356 int fd = -1;
81beb750
LP
3357 struct iovec iovec[5];
3358 int n = 0;
9e58ff9c
LP
3359
3360 assert(format);
3361
9ab7a8d2 3362 /* This is independent of logging, as status messages are
9e58ff9c
LP
3363 * optional and go exclusively to the console. */
3364
3365 if (vasprintf(&s, format, ap) < 0)
3366 goto finish;
3367
67e5cc4f 3368 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 3369 if (fd < 0)
9e58ff9c
LP
3370 goto finish;
3371
67e5cc4f 3372 if (ellipse) {
9ab7a8d2
MS
3373 char *e;
3374 size_t emax, sl;
3375 int c;
3376
67e5cc4f
LP
3377 c = fd_columns(fd);
3378 if (c <= 0)
3379 c = 80;
81beb750 3380
9ab7a8d2
MS
3381 sl = status ? strlen(status_indent) : 0;
3382
3383 emax = c - sl - 1;
3384 if (emax < 3)
3385 emax = 3;
81beb750 3386
67e5cc4f
LP
3387 e = ellipsize(s, emax, 75);
3388 if (e) {
3389 free(s);
3390 s = e;
3391 }
81beb750
LP
3392 }
3393
3394 zero(iovec);
81beb750 3395
9ab7a8d2
MS
3396 if (status) {
3397 if (!isempty(status)) {
3398 IOVEC_SET_STRING(iovec[n++], "[");
3399 IOVEC_SET_STRING(iovec[n++], status);
3400 IOVEC_SET_STRING(iovec[n++], "] ");
3401 } else
3402 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
3403 }
3404
9ab7a8d2
MS
3405 IOVEC_SET_STRING(iovec[n++], s);
3406 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750
LP
3407
3408 writev(fd, iovec, n);
9e58ff9c
LP
3409
3410finish:
3411 free(s);
3412
3413 if (fd >= 0)
3414 close_nointr_nofail(fd);
3415}
3416
67e5cc4f 3417void status_printf(const char *status, bool ellipse, const char *format, ...) {
c846ff47
LP
3418 va_list ap;
3419
3420 assert(format);
3421
3422 va_start(ap, format);
67e5cc4f 3423 status_vprintf(status, ellipse, format, ap);
c846ff47
LP
3424 va_end(ap);
3425}
3426
3427void status_welcome(void) {
10aa7034
LP
3428 char *pretty_name = NULL, *ansi_color = NULL;
3429 const char *const_pretty = NULL, *const_color = NULL;
3430 int r;
c846ff47 3431
10aa7034
LP
3432 if ((r = parse_env_file("/etc/os-release", NEWLINE,
3433 "PRETTY_NAME", &pretty_name,
3434 "ANSI_COLOR", &ansi_color,
3435 NULL)) < 0) {
c846ff47 3436
10aa7034
LP
3437 if (r != -ENOENT)
3438 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3439 }
c846ff47 3440
10aa7034
LP
3441 if (!pretty_name && !const_pretty)
3442 const_pretty = "Linux";
3443
3444 if (!ansi_color && !const_color)
3445 const_color = "1";
3446
81beb750 3447 status_printf(NULL,
67e5cc4f 3448 false,
81beb750 3449 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
10aa7034
LP
3450 const_color ? const_color : ansi_color,
3451 const_pretty ? const_pretty : pretty_name);
86a3475b
LP
3452
3453 free(ansi_color);
3454 free(pretty_name);
c846ff47
LP
3455}
3456
fab56fc5
LP
3457char *replace_env(const char *format, char **env) {
3458 enum {
3459 WORD,
c24eb49e 3460 CURLY,
fab56fc5
LP
3461 VARIABLE
3462 } state = WORD;
3463
3464 const char *e, *word = format;
3465 char *r = NULL, *k;
3466
3467 assert(format);
3468
3469 for (e = format; *e; e ++) {
3470
3471 switch (state) {
3472
3473 case WORD:
3474 if (*e == '$')
c24eb49e 3475 state = CURLY;
fab56fc5
LP
3476 break;
3477
c24eb49e
LP
3478 case CURLY:
3479 if (*e == '{') {
fab56fc5
LP
3480 if (!(k = strnappend(r, word, e-word-1)))
3481 goto fail;
3482
3483 free(r);
3484 r = k;
3485
3486 word = e-1;
3487 state = VARIABLE;
3488
3489 } else if (*e == '$') {
3490 if (!(k = strnappend(r, word, e-word)))
3491 goto fail;
3492
3493 free(r);
3494 r = k;
3495
3496 word = e+1;
3497 state = WORD;
3498 } else
3499 state = WORD;
3500 break;
3501
3502 case VARIABLE:
c24eb49e 3503 if (*e == '}') {
b95cf362 3504 const char *t;
fab56fc5 3505
b95cf362
LP
3506 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
3507 t = "";
fab56fc5 3508
b95cf362
LP
3509 if (!(k = strappend(r, t)))
3510 goto fail;
fab56fc5 3511
b95cf362
LP
3512 free(r);
3513 r = k;
fab56fc5 3514
b95cf362 3515 word = e+1;
fab56fc5
LP
3516 state = WORD;
3517 }
3518 break;
3519 }
3520 }
3521
3522 if (!(k = strnappend(r, word, e-word)))
3523 goto fail;
3524
3525 free(r);
3526 return k;
3527
3528fail:
3529 free(r);
3530 return NULL;
3531}
3532
3533char **replace_env_argv(char **argv, char **env) {
3534 char **r, **i;
c24eb49e
LP
3535 unsigned k = 0, l = 0;
3536
3537 l = strv_length(argv);
fab56fc5 3538
c24eb49e 3539 if (!(r = new(char*, l+1)))
fab56fc5
LP
3540 return NULL;
3541
3542 STRV_FOREACH(i, argv) {
c24eb49e
LP
3543
3544 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3545 if ((*i)[0] == '$' && (*i)[1] != '{') {
3546 char *e;
3547 char **w, **m;
3548 unsigned q;
c24eb49e 3549
b95cf362 3550 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
3551
3552 if (!(m = strv_split_quoted(e))) {
3553 r[k] = NULL;
3554 strv_free(r);
3555 return NULL;
3556 }
b95cf362
LP
3557 } else
3558 m = NULL;
c24eb49e 3559
b95cf362
LP
3560 q = strv_length(m);
3561 l = l + q - 1;
c24eb49e 3562
b95cf362
LP
3563 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3564 r[k] = NULL;
3565 strv_free(r);
3566 strv_free(m);
3567 return NULL;
3568 }
c24eb49e 3569
b95cf362
LP
3570 r = w;
3571 if (m) {
c24eb49e
LP
3572 memcpy(r + k, m, q * sizeof(char*));
3573 free(m);
c24eb49e 3574 }
b95cf362
LP
3575
3576 k += q;
3577 continue;
c24eb49e
LP
3578 }
3579
3580 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3581 if (!(r[k++] = replace_env(*i, env))) {
3582 strv_free(r);
3583 return NULL;
3584 }
3585 }
3586
3587 r[k] = NULL;
3588 return r;
3589}
3590
81beb750
LP
3591int fd_columns(int fd) {
3592 struct winsize ws;
3593 zero(ws);
3594
3595 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3596 return -errno;
3597
3598 if (ws.ws_col <= 0)
3599 return -EIO;
3600
3601 return ws.ws_col;
3602}
3603
72f59706 3604unsigned columns(void) {
fa776d8e
LP
3605 static __thread int parsed_columns = 0;
3606 const char *e;
3607
3bfc7184 3608 if (_likely_(parsed_columns > 0))
fa776d8e
LP
3609 return parsed_columns;
3610
81beb750
LP
3611 e = getenv("COLUMNS");
3612 if (e)
fa776d8e
LP
3613 parsed_columns = atoi(e);
3614
81beb750
LP
3615 if (parsed_columns <= 0)
3616 parsed_columns = fd_columns(STDOUT_FILENO);
fa776d8e
LP
3617
3618 if (parsed_columns <= 0)
3619 parsed_columns = 80;
3620
3621 return parsed_columns;
3622}
3623
8f2d43a0
LP
3624int fd_lines(int fd) {
3625 struct winsize ws;
3626 zero(ws);
3627
3628 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3629 return -errno;
3630
3631 if (ws.ws_row <= 0)
3632 return -EIO;
3633
3634 return ws.ws_row;
3635}
3636
3637unsigned lines(void) {
3638 static __thread int parsed_lines = 0;
3639 const char *e;
3640
3641 if (_likely_(parsed_lines > 0))
3642 return parsed_lines;
3643
3644 e = getenv("LINES");
3645 if (e)
3646 parsed_lines = atoi(e);
3647
3648 if (parsed_lines <= 0)
3649 parsed_lines = fd_lines(STDOUT_FILENO);
3650
3651 if (parsed_lines <= 0)
3652 parsed_lines = 25;
3653
3654 return parsed_lines;
3655}
3656
b4f10a5e
LP
3657int running_in_chroot(void) {
3658 struct stat a, b;
3659
3660 zero(a);
3661 zero(b);
3662
3663 /* Only works as root */
3664
3665 if (stat("/proc/1/root", &a) < 0)
3666 return -errno;
3667
3668 if (stat("/", &b) < 0)
3669 return -errno;
3670
3671 return
3672 a.st_dev != b.st_dev ||
3673 a.st_ino != b.st_ino;
3674}
3675
72f59706
LP
3676char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3677 size_t x;
8fe914ec
LP
3678 char *r;
3679
3680 assert(s);
3681 assert(percent <= 100);
72f59706 3682 assert(new_length >= 3);
8fe914ec 3683
72f59706
LP
3684 if (old_length <= 3 || old_length <= new_length)
3685 return strndup(s, old_length);
8fe914ec 3686
72f59706
LP
3687 r = new0(char, new_length+1);
3688 if (!r)
8fe914ec
LP
3689 return r;
3690
72f59706 3691 x = (new_length * percent) / 100;
8fe914ec 3692
72f59706
LP
3693 if (x > new_length - 3)
3694 x = new_length - 3;
8fe914ec
LP
3695
3696 memcpy(r, s, x);
3697 r[x] = '.';
3698 r[x+1] = '.';
3699 r[x+2] = '.';
3700 memcpy(r + x + 3,
72f59706
LP
3701 s + old_length - (new_length - x - 3),
3702 new_length - x - 3);
8fe914ec
LP
3703
3704 return r;
3705}
3706
72f59706
LP
3707char *ellipsize(const char *s, size_t length, unsigned percent) {
3708 return ellipsize_mem(s, strlen(s), length, percent);
3709}
3710
f6144808
LP
3711int touch(const char *path) {
3712 int fd;
3713
3714 assert(path);
3715
14f3c825 3716 if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644)) < 0)
f6144808
LP
3717 return -errno;
3718
3719 close_nointr_nofail(fd);
3720 return 0;
3721}
afea26ad 3722
97c4a07d 3723char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3724 size_t l;
3725 assert(s);
3726
31ed59c5
LP
3727 l = strlen(s);
3728 if (l < 2)
11ce3427
LP
3729 return strdup(s);
3730
97c4a07d 3731 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3732 return strndup(s+1, l-2);
3733
3734 return strdup(s);
3735}
3736
5f7c426e
LP
3737char *normalize_env_assignment(const char *s) {
3738 char *name, *value, *p, *r;
3739
3740 p = strchr(s, '=');
3741
3742 if (!p) {
3743 if (!(r = strdup(s)))
3744 return NULL;
3745
3746 return strstrip(r);
3747 }
3748
3749 if (!(name = strndup(s, p - s)))
3750 return NULL;
3751
3752 if (!(p = strdup(p+1))) {
3753 free(name);
3754 return NULL;
3755 }
3756
3757 value = unquote(strstrip(p), QUOTES);
3758 free(p);
3759
3760 if (!value) {
5f7c426e
LP
3761 free(name);
3762 return NULL;
3763 }
3764
3765 if (asprintf(&r, "%s=%s", name, value) < 0)
3766 r = NULL;
3767
3768 free(value);
3769 free(name);
3770
3771 return r;
3772}
3773
8e12a6ae 3774int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
3775 siginfo_t dummy;
3776
2e78aa99 3777 assert(pid >= 1);
1968a360
LP
3778
3779 if (!status)
3780 status = &dummy;
2e78aa99
LP
3781
3782 for (;;) {
8e12a6ae
LP
3783 zero(*status);
3784
3785 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
3786
3787 if (errno == EINTR)
3788 continue;
3789
3790 return -errno;
3791 }
3792
3793 return 0;
3794 }
3795}
3796
97c4a07d
LP
3797int wait_for_terminate_and_warn(const char *name, pid_t pid) {
3798 int r;
3799 siginfo_t status;
3800
3801 assert(name);
3802 assert(pid > 1);
3803
3804 if ((r = wait_for_terminate(pid, &status)) < 0) {
3805 log_warning("Failed to wait for %s: %s", name, strerror(-r));
3806 return r;
3807 }
3808
3809 if (status.si_code == CLD_EXITED) {
3810 if (status.si_status != 0) {
3811 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3812 return status.si_status;
97c4a07d
LP
3813 }
3814
3815 log_debug("%s succeeded.", name);
3816 return 0;
3817
3818 } else if (status.si_code == CLD_KILLED ||
3819 status.si_code == CLD_DUMPED) {
3820
3821 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3822 return -EPROTO;
3823 }
3824
3825 log_warning("%s failed due to unknown reason.", name);
3826 return -EPROTO;
3827
3828}
3829
6a39419f 3830_noreturn_ void freeze(void) {
720ce21d
LP
3831
3832 /* Make sure nobody waits for us on a socket anymore */
3833 close_all_fds(NULL, 0);
3834
c29597a1
LP
3835 sync();
3836
3c14d26c
LP
3837 for (;;)
3838 pause();
3839}
3840
00dc5d76
LP
3841bool null_or_empty(struct stat *st) {
3842 assert(st);
3843
3844 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3845 return true;
3846
c8f26f42 3847 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3848 return true;
3849
3850 return false;
3851}
3852
83096483
LP
3853int null_or_empty_path(const char *fn) {
3854 struct stat st;
3855
3856 assert(fn);
3857
3858 if (stat(fn, &st) < 0)
3859 return -errno;
3860
3861 return null_or_empty(&st);
3862}
3863
a247755d 3864DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3865 int nfd;
3866 DIR *d;
3867
3868 if ((nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags)) < 0)
3869 return NULL;
3870
3871 if (!(d = fdopendir(nfd))) {
3872 close_nointr_nofail(nfd);
3873 return NULL;
3874 }
3875
3876 return d;
3b63d2d3
LP
3877}
3878
8a0867d6
LP
3879int signal_from_string_try_harder(const char *s) {
3880 int signo;
3881 assert(s);
3882
3883 if ((signo = signal_from_string(s)) <= 0)
3884 if (startswith(s, "SIG"))
3885 return signal_from_string(s+3);
3886
3887 return signo;
3888}
3889
10717a1a
LP
3890void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
3891
3892 assert(f);
3893 assert(name);
3894 assert(t);
3895
3896 if (!dual_timestamp_is_set(t))
3897 return;
3898
3899 fprintf(f, "%s=%llu %llu\n",
3900 name,
3901 (unsigned long long) t->realtime,
3902 (unsigned long long) t->monotonic);
3903}
3904
799fd0fd 3905void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
10717a1a
LP
3906 unsigned long long a, b;
3907
10717a1a
LP
3908 assert(value);
3909 assert(t);
3910
3911 if (sscanf(value, "%lli %llu", &a, &b) != 2)
3912 log_debug("Failed to parse finish timestamp value %s", value);
3913 else {
3914 t->realtime = a;
3915 t->monotonic = b;
3916 }
3917}
3918
e23a0ce8
LP
3919char *fstab_node_to_udev_node(const char *p) {
3920 char *dn, *t, *u;
3921 int r;
3922
3923 /* FIXME: to follow udev's logic 100% we need to leave valid
3924 * UTF8 chars unescaped */
3925
3926 if (startswith(p, "LABEL=")) {
3927
3928 if (!(u = unquote(p+6, "\"\'")))
3929 return NULL;
3930
3931 t = xescape(u, "/ ");
3932 free(u);
3933
3934 if (!t)
3935 return NULL;
3936
3937 r = asprintf(&dn, "/dev/disk/by-label/%s", t);
3938 free(t);
3939
3940 if (r < 0)
3941 return NULL;
3942
3943 return dn;
3944 }
3945
3946 if (startswith(p, "UUID=")) {
3947
3948 if (!(u = unquote(p+5, "\"\'")))
3949 return NULL;
3950
3951 t = xescape(u, "/ ");
3952 free(u);
3953
3954 if (!t)
3955 return NULL;
3956
0058d7b9 3957 r = asprintf(&dn, "/dev/disk/by-uuid/%s", t);
e23a0ce8
LP
3958 free(t);
3959
3960 if (r < 0)
3961 return NULL;
3962
3963 return dn;
3964 }
3965
3966 return strdup(p);
3967}
3968
f212ac12
LP
3969bool tty_is_vc(const char *tty) {
3970 assert(tty);
3971
3972 if (startswith(tty, "/dev/"))
3973 tty += 5;
3974
98a28fef
LP
3975 return vtnr_from_tty(tty) >= 0;
3976}
3977
d1122ad5
LP
3978bool tty_is_console(const char *tty) {
3979 assert(tty);
3980
3981 if (startswith(tty, "/dev/"))
3982 tty += 5;
3983
3984 return streq(tty, "console");
3985}
3986
98a28fef
LP
3987int vtnr_from_tty(const char *tty) {
3988 int i, r;
3989
3990 assert(tty);
3991
3992 if (startswith(tty, "/dev/"))
3993 tty += 5;
3994
3995 if (!startswith(tty, "tty") )
3996 return -EINVAL;
3997
3998 if (tty[3] < '0' || tty[3] > '9')
3999 return -EINVAL;
4000
4001 r = safe_atoi(tty+3, &i);
4002 if (r < 0)
4003 return r;
4004
4005 if (i < 0 || i > 63)
4006 return -EINVAL;
4007
4008 return i;
f212ac12
LP
4009}
4010
3043935f 4011bool tty_is_vc_resolve(const char *tty) {
3030ccd7 4012 char *active = NULL;
3043935f 4013 bool b;
3030ccd7 4014
e3aa71c3
LP
4015 assert(tty);
4016
4017 if (startswith(tty, "/dev/"))
4018 tty += 5;
4019
3d9a4122
LP
4020 /* Resolve where /dev/console is pointing to, if /sys is
4021 * actually ours (i.e. not read-only-mounted which is a sign
4022 * for container setups) */
4023 if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
3030ccd7 4024 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4025 /* If multiple log outputs are configured the
4026 * last one is what /dev/console points to */
3043935f
LP
4027 tty = strrchr(active, ' ');
4028 if (tty)
079a09fb
LP
4029 tty++;
4030 else
4031 tty = active;
3030ccd7
LP
4032 }
4033
3043935f 4034 b = tty_is_vc(tty);
3030ccd7 4035 free(active);
e3aa71c3 4036
3043935f
LP
4037 return b;
4038}
4039
4040const char *default_term_for_tty(const char *tty) {
4041 assert(tty);
4042
acda6a05 4043 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
4044}
4045
87d2c1ff 4046bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4047 assert(de);
4048
4049 if (ignore_file(de->d_name))
4050 return false;
4051
4052 if (de->d_type != DT_REG &&
4053 de->d_type != DT_LNK &&
4054 de->d_type != DT_UNKNOWN)
4055 return false;
4056
4057 return true;
4058}
4059
87d2c1ff
LP
4060bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4061 assert(de);
4062
4063 if (!dirent_is_file(de))
4064 return false;
4065
4066 return endswith(de->d_name, suffix);
4067}
4068
83cc030f
LP
4069void execute_directory(const char *directory, DIR *d, char *argv[]) {
4070 DIR *_d = NULL;
4071 struct dirent *de;
4072 Hashmap *pids = NULL;
4073
4074 assert(directory);
4075
4076 /* Executes all binaries in a directory in parallel and waits
4077 * until all they all finished. */
4078
4079 if (!d) {
4080 if (!(_d = opendir(directory))) {
4081
4082 if (errno == ENOENT)
4083 return;
4084
4085 log_error("Failed to enumerate directory %s: %m", directory);
4086 return;
4087 }
4088
4089 d = _d;
4090 }
4091
4092 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4093 log_error("Failed to allocate set.");
4094 goto finish;
4095 }
4096
4097 while ((de = readdir(d))) {
4098 char *path;
4099 pid_t pid;
4100 int k;
4101
fb19a739 4102 if (!dirent_is_file(de))
83cc030f
LP
4103 continue;
4104
4105 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
4106 log_error("Out of memory");
4107 continue;
4108 }
4109
4110 if ((pid = fork()) < 0) {
4111 log_error("Failed to fork: %m");
4112 free(path);
4113 continue;
4114 }
4115
4116 if (pid == 0) {
4117 char *_argv[2];
4118 /* Child */
4119
4120 if (!argv) {
4121 _argv[0] = path;
4122 _argv[1] = NULL;
4123 argv = _argv;
4124 } else
6edd7d0a 4125 argv[0] = path;
83cc030f
LP
4126
4127 execv(path, argv);
4128
4129 log_error("Failed to execute %s: %m", path);
4130 _exit(EXIT_FAILURE);
4131 }
4132
4133 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4134
4135 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4136 log_error("Failed to add PID to set: %s", strerror(-k));
4137 free(path);
4138 }
4139 }
4140
4141 while (!hashmap_isempty(pids)) {
ec3f9b53 4142 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
4143 siginfo_t si;
4144 char *path;
4145
4146 zero(si);
ec3f9b53 4147 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
4148
4149 if (errno == EINTR)
4150 continue;
4151
4152 log_error("waitid() failed: %m");
4153 goto finish;
4154 }
4155
4156 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
4157 if (!is_clean_exit(si.si_code, si.si_status)) {
4158 if (si.si_code == CLD_EXITED)
4159 log_error("%s exited with exit status %i.", path, si.si_status);
4160 else
4161 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4162 } else
4163 log_debug("%s exited successfully.", path);
4164
4165 free(path);
4166 }
4167 }
4168
4169finish:
4170 if (_d)
4171 closedir(_d);
4172
4173 if (pids)
4174 hashmap_free_free(pids);
4175}
4176
430c18ed
LP
4177int kill_and_sigcont(pid_t pid, int sig) {
4178 int r;
4179
4180 r = kill(pid, sig) < 0 ? -errno : 0;
4181
4182 if (r >= 0)
4183 kill(pid, SIGCONT);
4184
4185 return r;
4186}
4187
05feefe0
LP
4188bool nulstr_contains(const char*nulstr, const char *needle) {
4189 const char *i;
4190
4191 if (!nulstr)
4192 return false;
4193
4194 NULSTR_FOREACH(i, nulstr)
4195 if (streq(i, needle))
4196 return true;
4197
4198 return false;
4199}
4200
6faa1114 4201bool plymouth_running(void) {
9408a2d2 4202 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4203}
4204
7c3b203c
LP
4205void parse_syslog_priority(char **p, int *priority) {
4206 int a = 0, b = 0, c = 0;
4207 int k;
4208
4209 assert(p);
4210 assert(*p);
4211 assert(priority);
4212
4213 if ((*p)[0] != '<')
4214 return;
4215
4216 if (!strchr(*p, '>'))
4217 return;
4218
4219 if ((*p)[2] == '>') {
4220 c = undecchar((*p)[1]);
4221 k = 3;
4222 } else if ((*p)[3] == '>') {
4223 b = undecchar((*p)[1]);
4224 c = undecchar((*p)[2]);
4225 k = 4;
4226 } else if ((*p)[4] == '>') {
4227 a = undecchar((*p)[1]);
4228 b = undecchar((*p)[2]);
4229 c = undecchar((*p)[3]);
4230 k = 5;
4231 } else
4232 return;
4233
4234 if (a < 0 || b < 0 || c < 0)
4235 return;
4236
4237 *priority = a*100+b*10+c;
4238 *p += k;
4239}
4240
87d2c1ff
LP
4241void skip_syslog_pid(char **buf) {
4242 char *p;
4243
4244 assert(buf);
4245 assert(*buf);
4246
4247 p = *buf;
4248
4249 if (*p != '[')
4250 return;
4251
4252 p++;
4253 p += strspn(p, "0123456789");
4254
4255 if (*p != ']')
4256 return;
4257
4258 p++;
4259
4260 *buf = p;
4261}
4262
4263void skip_syslog_date(char **buf) {
4264 enum {
4265 LETTER,
4266 SPACE,
4267 NUMBER,
4268 SPACE_OR_NUMBER,
4269 COLON
4270 } sequence[] = {
4271 LETTER, LETTER, LETTER,
4272 SPACE,
4273 SPACE_OR_NUMBER, NUMBER,
4274 SPACE,
4275 SPACE_OR_NUMBER, NUMBER,
4276 COLON,
4277 SPACE_OR_NUMBER, NUMBER,
4278 COLON,
4279 SPACE_OR_NUMBER, NUMBER,
4280 SPACE
4281 };
4282
4283 char *p;
4284 unsigned i;
4285
4286 assert(buf);
4287 assert(*buf);
4288
4289 p = *buf;
4290
4291 for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
4292
4293 if (!*p)
4294 return;
4295
4296 switch (sequence[i]) {
4297
4298 case SPACE:
4299 if (*p != ' ')
4300 return;
4301 break;
4302
4303 case SPACE_OR_NUMBER:
4304 if (*p == ' ')
4305 break;
4306
4307 /* fall through */
4308
4309 case NUMBER:
4310 if (*p < '0' || *p > '9')
4311 return;
4312
4313 break;
4314
4315 case LETTER:
4316 if (!(*p >= 'A' && *p <= 'Z') &&
4317 !(*p >= 'a' && *p <= 'z'))
4318 return;
4319
4320 break;
4321
4322 case COLON:
4323 if (*p != ':')
4324 return;
4325 break;
4326
4327 }
4328 }
4329
4330 *buf = p;
4331}
4332
9beb3f4d
LP
4333char* strshorten(char *s, size_t l) {
4334 assert(s);
4335
4336 if (l < strlen(s))
4337 s[l] = 0;
4338
4339 return s;
4340}
4341
4342static bool hostname_valid_char(char c) {
4343 return
4344 (c >= 'a' && c <= 'z') ||
4345 (c >= 'A' && c <= 'Z') ||
4346 (c >= '0' && c <= '9') ||
4347 c == '-' ||
4348 c == '_' ||
4349 c == '.';
4350}
4351
4352bool hostname_is_valid(const char *s) {
4353 const char *p;
4354
4355 if (isempty(s))
4356 return false;
4357
4358 for (p = s; *p; p++)
4359 if (!hostname_valid_char(*p))
4360 return false;
4361
4362 if (p-s > HOST_NAME_MAX)
4363 return false;
4364
4365 return true;
4366}
4367
4368char* hostname_cleanup(char *s) {
4369 char *p, *d;
4370
4371 for (p = s, d = s; *p; p++)
4372 if ((*p >= 'a' && *p <= 'z') ||
4373 (*p >= 'A' && *p <= 'Z') ||
4374 (*p >= '0' && *p <= '9') ||
4375 *p == '-' ||
4376 *p == '_' ||
4377 *p == '.')
4378 *(d++) = *p;
4379
4380 *d = 0;
4381
4382 strshorten(s, HOST_NAME_MAX);
4383 return s;
4384}
4385
1325aa42
LP
4386int pipe_eof(int fd) {
4387 struct pollfd pollfd;
4388 int r;
4389
4390 zero(pollfd);
4391 pollfd.fd = fd;
4392 pollfd.events = POLLIN|POLLHUP;
4393
4394 r = poll(&pollfd, 1, 0);
4395 if (r < 0)
4396 return -errno;
4397
4398 if (r == 0)
4399 return 0;
4400
4401 return pollfd.revents & POLLHUP;
4402}
4403
8f2d43a0 4404int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
4405 struct pollfd pollfd;
4406 int r;
4407
4408 zero(pollfd);
4409 pollfd.fd = fd;
4410 pollfd.events = event;
4411
8f2d43a0 4412 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
4413 if (r < 0)
4414 return -errno;
4415
4416 if (r == 0)
4417 return 0;
4418
4419 return pollfd.revents;
4420}
4421
5a3ab509
LP
4422int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4423 FILE *f;
4424 char *t;
4425 const char *fn;
4426 size_t k;
4427 int fd;
4428
4429 assert(path);
4430 assert(_f);
4431 assert(_temp_path);
4432
4433 t = new(char, strlen(path) + 1 + 6 + 1);
4434 if (!t)
4435 return -ENOMEM;
4436
9eb977db 4437 fn = path_get_file_name(path);
5a3ab509
LP
4438 k = fn-path;
4439 memcpy(t, path, k);
4440 t[k] = '.';
4441 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4442
4443 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4444 if (fd < 0) {
4445 free(t);
4446 return -errno;
4447 }
4448
4449 f = fdopen(fd, "we");
4450 if (!f) {
4451 unlink(t);
4452 free(t);
4453 return -errno;
4454 }
4455
4456 *_f = f;
4457 *_temp_path = t;
4458
4459 return 0;
4460}
4461
6ea832a2 4462int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4463 assert(fd >= 0);
4464
6ea832a2
LP
4465 if (ioctl(fd, TIOCVHANGUP) < 0)
4466 return -errno;
4467
4468 return 0;
4469}
4470
4471int terminal_vhangup(const char *name) {
4472 int fd, r;
4473
4474 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4475 if (fd < 0)
4476 return fd;
4477
4478 r = terminal_vhangup_fd(fd);
4479 close_nointr_nofail(fd);
4480
4481 return r;
4482}
4483
4484int vt_disallocate(const char *name) {
4485 int fd, r;
4486 unsigned u;
6ea832a2
LP
4487
4488 /* Deallocate the VT if possible. If not possible
4489 * (i.e. because it is the active one), at least clear it
4490 * entirely (including the scrollback buffer) */
4491
b83bc4e9
LP
4492 if (!startswith(name, "/dev/"))
4493 return -EINVAL;
4494
4495 if (!tty_is_vc(name)) {
4496 /* So this is not a VT. I guess we cannot deallocate
4497 * it then. But let's at least clear the screen */
4498
4499 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4500 if (fd < 0)
4501 return fd;
4502
8585357a
LP
4503 loop_write(fd,
4504 "\033[r" /* clear scrolling region */
4505 "\033[H" /* move home */
4506 "\033[2J", /* clear screen */
4507 10, false);
b83bc4e9
LP
4508 close_nointr_nofail(fd);
4509
4510 return 0;
4511 }
6ea832a2
LP
4512
4513 if (!startswith(name, "/dev/tty"))
4514 return -EINVAL;
4515
4516 r = safe_atou(name+8, &u);
4517 if (r < 0)
4518 return r;
4519
4520 if (u <= 0)
b83bc4e9 4521 return -EINVAL;
6ea832a2 4522
b83bc4e9 4523 /* Try to deallocate */
6ea832a2
LP
4524 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4525 if (fd < 0)
4526 return fd;
4527
4528 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4529 close_nointr_nofail(fd);
6ea832a2 4530
b83bc4e9
LP
4531 if (r >= 0)
4532 return 0;
6ea832a2 4533
b83bc4e9 4534 if (errno != EBUSY)
6ea832a2 4535 return -errno;
6ea832a2 4536
b83bc4e9
LP
4537 /* Couldn't deallocate, so let's clear it fully with
4538 * scrollback */
4539 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4540 if (fd < 0)
b83bc4e9 4541 return fd;
6ea832a2 4542
8585357a
LP
4543 loop_write(fd,
4544 "\033[r" /* clear scrolling region */
4545 "\033[H" /* move home */
4546 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4547 10, false);
b83bc4e9 4548 close_nointr_nofail(fd);
6ea832a2 4549
b83bc4e9 4550 return 0;
6ea832a2
LP
4551}
4552
34ca941c
LP
4553int copy_file(const char *from, const char *to) {
4554 int r, fdf, fdt;
4555
4556 assert(from);
4557 assert(to);
4558
4559 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4560 if (fdf < 0)
4561 return -errno;
4562
4563 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4564 if (fdt < 0) {
4565 close_nointr_nofail(fdf);
4566 return -errno;
4567 }
4568
4569 for (;;) {
4570 char buf[PIPE_BUF];
4571 ssize_t n, k;
4572
4573 n = read(fdf, buf, sizeof(buf));
4574 if (n < 0) {
4575 r = -errno;
4576
4577 close_nointr_nofail(fdf);
4578 close_nointr(fdt);
4579 unlink(to);
4580
4581 return r;
4582 }
4583
4584 if (n == 0)
4585 break;
4586
4587 errno = 0;
4588 k = loop_write(fdt, buf, n, false);
4589 if (n != k) {
4590 r = k < 0 ? k : (errno ? -errno : -EIO);
4591
4592 close_nointr_nofail(fdf);
4593 close_nointr(fdt);
4594
4595 unlink(to);
4596 return r;
4597 }
4598 }
4599
4600 close_nointr_nofail(fdf);
4601 r = close_nointr(fdt);
4602
4603 if (r < 0) {
4604 unlink(to);
4605 return r;
4606 }
4607
4608 return 0;
4609}
4610
4611int symlink_or_copy(const char *from, const char *to) {
4612 char *pf = NULL, *pt = NULL;
4613 struct stat a, b;
4614 int r;
4615
4616 assert(from);
4617 assert(to);
4618
9eb977db
KS
4619 if (path_get_parent(from, &pf) < 0 ||
4620 path_get_parent(to, &pt) < 0) {
34ca941c
LP
4621 r = -ENOMEM;
4622 goto finish;
4623 }
4624
4625 if (stat(pf, &a) < 0 ||
4626 stat(pt, &b) < 0) {
4627 r = -errno;
4628 goto finish;
4629 }
4630
4631 if (a.st_dev != b.st_dev) {
4632 free(pf);
4633 free(pt);
4634
4635 return copy_file(from, to);
4636 }
4637
4638 if (symlink(from, to) < 0) {
4639 r = -errno;
4640 goto finish;
4641 }
4642
4643 r = 0;
4644
4645finish:
4646 free(pf);
4647 free(pt);
4648
4649 return r;
4650}
4651
4652int symlink_or_copy_atomic(const char *from, const char *to) {
4653 char *t, *x;
4654 const char *fn;
4655 size_t k;
4656 unsigned long long ull;
4657 unsigned i;
4658 int r;
4659
4660 assert(from);
4661 assert(to);
4662
4663 t = new(char, strlen(to) + 1 + 16 + 1);
4664 if (!t)
4665 return -ENOMEM;
4666
9eb977db 4667 fn = path_get_file_name(to);
34ca941c
LP
4668 k = fn-to;
4669 memcpy(t, to, k);
4670 t[k] = '.';
4671 x = stpcpy(t+k+1, fn);
4672
4673 ull = random_ull();
4674 for (i = 0; i < 16; i++) {
4675 *(x++) = hexchar(ull & 0xF);
4676 ull >>= 4;
4677 }
4678
4679 *x = 0;
4680
4681 r = symlink_or_copy(from, t);
4682 if (r < 0) {
4683 unlink(t);
4684 free(t);
4685 return r;
4686 }
4687
4688 if (rename(t, to) < 0) {
4689 r = -errno;
4690 unlink(t);
4691 free(t);
4692 return r;
4693 }
4694
4695 free(t);
4696 return r;
4697}
4698
4d6d6518
LP
4699bool display_is_local(const char *display) {
4700 assert(display);
4701
4702 return
4703 display[0] == ':' &&
4704 display[1] >= '0' &&
4705 display[1] <= '9';
4706}
4707
4708int socket_from_display(const char *display, char **path) {
4709 size_t k;
4710 char *f, *c;
4711
4712 assert(display);
4713 assert(path);
4714
4715 if (!display_is_local(display))
4716 return -EINVAL;
4717
4718 k = strspn(display+1, "0123456789");
4719
4720 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4721 if (!f)
4722 return -ENOMEM;
4723
4724 c = stpcpy(f, "/tmp/.X11-unix/X");
4725 memcpy(c, display+1, k);
4726 c[k] = 0;
4727
4728 *path = f;
4729
4730 return 0;
4731}
4732
1cccf435
MV
4733int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
4734 struct passwd *p;
ddd88763 4735 uid_t u;
1cccf435
MV
4736
4737 assert(username);
4738 assert(*username);
1cccf435
MV
4739
4740 /* We enforce some special rules for uid=0: in order to avoid
4741 * NSS lookups for root we hardcode its data. */
4742
4743 if (streq(*username, "root") || streq(*username, "0")) {
4744 *username = "root";
4b67834e
LP
4745
4746 if (uid)
4747 *uid = 0;
4748
4749 if (gid)
4750 *gid = 0;
4751
4752 if (home)
4753 *home = "/root";
1cccf435
MV
4754 return 0;
4755 }
4756
ddd88763 4757 if (parse_uid(*username, &u) >= 0) {
1cccf435 4758 errno = 0;
ddd88763 4759 p = getpwuid(u);
1cccf435
MV
4760
4761 /* If there are multiple users with the same id, make
4762 * sure to leave $USER to the configured value instead
4763 * of the first occurrence in the database. However if
4764 * the uid was configured by a numeric uid, then let's
4765 * pick the real username from /etc/passwd. */
4766 if (p)
4767 *username = p->pw_name;
4768 } else {
4769 errno = 0;
4770 p = getpwnam(*username);
4771 }
4772
4773 if (!p)
4774 return errno != 0 ? -errno : -ESRCH;
4775
4b67834e
LP
4776 if (uid)
4777 *uid = p->pw_uid;
4778
4779 if (gid)
4780 *gid = p->pw_gid;
4781
4782 if (home)
4783 *home = p->pw_dir;
4784
4785 return 0;
4786}
4787
4788int get_group_creds(const char **groupname, gid_t *gid) {
4789 struct group *g;
4790 gid_t id;
4791
4792 assert(groupname);
4793
4794 /* We enforce some special rules for gid=0: in order to avoid
4795 * NSS lookups for root we hardcode its data. */
4796
4797 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4798 *groupname = "root";
4799
4800 if (gid)
4801 *gid = 0;
4802
4803 return 0;
4804 }
4805
4806 if (parse_gid(*groupname, &id) >= 0) {
4807 errno = 0;
4808 g = getgrgid(id);
4809
4810 if (g)
4811 *groupname = g->gr_name;
4812 } else {
4813 errno = 0;
4814 g = getgrnam(*groupname);
4815 }
4816
4817 if (!g)
4818 return errno != 0 ? -errno : -ESRCH;
4819
4820 if (gid)
4821 *gid = g->gr_gid;
4822
1cccf435
MV
4823 return 0;
4824}
4825
43673799
LP
4826int in_group(const char *name) {
4827 gid_t gid, *gids;
4828 int ngroups_max, r, i;
4829
4830 r = get_group_creds(&name, &gid);
4831 if (r < 0)
4832 return r;
4833
4834 if (getgid() == gid)
4835 return 1;
4836
4837 if (getegid() == gid)
4838 return 1;
4839
4840 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4841 assert(ngroups_max > 0);
4842
4843 gids = alloca(sizeof(gid_t) * ngroups_max);
4844
4845 r = getgroups(ngroups_max, gids);
4846 if (r < 0)
4847 return -errno;
4848
4849 for (i = 0; i < r; i++)
4850 if (gids[i] == gid)
4851 return 1;
4852
4853 return 0;
4854}
4855
8092a428
LP
4856int glob_exists(const char *path) {
4857 glob_t g;
4858 int r, k;
4859
4860 assert(path);
4861
4862 zero(g);
4863 errno = 0;
4864 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4865
4866 if (k == GLOB_NOMATCH)
4867 r = 0;
4868 else if (k == GLOB_NOSPACE)
4869 r = -ENOMEM;
4870 else if (k == 0)
4871 r = !strv_isempty(g.gl_pathv);
4872 else
4873 r = errno ? -errno : -EIO;
4874
4875 globfree(&g);
4876
4877 return r;
4878}
4879
83096483
LP
4880int dirent_ensure_type(DIR *d, struct dirent *de) {
4881 struct stat st;
4882
4883 assert(d);
4884 assert(de);
4885
4886 if (de->d_type != DT_UNKNOWN)
4887 return 0;
4888
4889 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4890 return -errno;
4891
4892 de->d_type =
4893 S_ISREG(st.st_mode) ? DT_REG :
4894 S_ISDIR(st.st_mode) ? DT_DIR :
4895 S_ISLNK(st.st_mode) ? DT_LNK :
4896 S_ISFIFO(st.st_mode) ? DT_FIFO :
4897 S_ISSOCK(st.st_mode) ? DT_SOCK :
4898 S_ISCHR(st.st_mode) ? DT_CHR :
4899 S_ISBLK(st.st_mode) ? DT_BLK :
4900 DT_UNKNOWN;
4901
4902 return 0;
4903}
4904
4905int in_search_path(const char *path, char **search) {
4906 char **i, *parent;
4907 int r;
4908
9eb977db 4909 r = path_get_parent(path, &parent);
83096483
LP
4910 if (r < 0)
4911 return r;
4912
4913 r = 0;
4914
4915 STRV_FOREACH(i, search) {
4916 if (path_equal(parent, *i)) {
4917 r = 1;
4918 break;
4919 }
4920 }
4921
4922 free(parent);
4923
4924 return r;
4925}
4926
034a2a52
LP
4927int get_files_in_directory(const char *path, char ***list) {
4928 DIR *d;
4929 int r = 0;
4930 unsigned n = 0;
4931 char **l = NULL;
4932
4933 assert(path);
d60ef526
LP
4934
4935 /* Returns all files in a directory in *list, and the number
4936 * of files as return value. If list is NULL returns only the
4937 * number */
034a2a52
LP
4938
4939 d = opendir(path);
8ea913b2
LP
4940 if (!d)
4941 return -errno;
4942
034a2a52
LP
4943 for (;;) {
4944 struct dirent buffer, *de;
4945 int k;
4946
4947 k = readdir_r(d, &buffer, &de);
4948 if (k != 0) {
4949 r = -k;
4950 goto finish;
4951 }
4952
4953 if (!de)
4954 break;
4955
4956 dirent_ensure_type(d, de);
4957
4958 if (!dirent_is_file(de))
4959 continue;
4960
d60ef526
LP
4961 if (list) {
4962 if ((unsigned) r >= n) {
4963 char **t;
034a2a52 4964
d60ef526
LP
4965 n = MAX(16, 2*r);
4966 t = realloc(l, sizeof(char*) * n);
4967 if (!t) {
4968 r = -ENOMEM;
4969 goto finish;
4970 }
034a2a52 4971
d60ef526
LP
4972 l = t;
4973 }
034a2a52 4974
d60ef526 4975 assert((unsigned) r < n);
034a2a52 4976
d60ef526
LP
4977 l[r] = strdup(de->d_name);
4978 if (!l[r]) {
4979 r = -ENOMEM;
4980 goto finish;
4981 }
034a2a52 4982
d60ef526
LP
4983 l[++r] = NULL;
4984 } else
4985 r++;
034a2a52
LP
4986 }
4987
4988finish:
4989 if (d)
4990 closedir(d);
4991
d60ef526
LP
4992 if (r >= 0) {
4993 if (list)
4994 *list = l;
4995 } else
034a2a52
LP
4996 strv_free(l);
4997
4998 return r;
4999}
5000
911a4828
LP
5001char *join(const char *x, ...) {
5002 va_list ap;
5003 size_t l;
5004 char *r, *p;
5005
5006 va_start(ap, x);
5007
5008 if (x) {
5009 l = strlen(x);
5010
5011 for (;;) {
5012 const char *t;
5013
5014 t = va_arg(ap, const char *);
5015 if (!t)
5016 break;
5017
5018 l += strlen(t);
5019 }
5020 } else
5021 l = 0;
5022
5023 va_end(ap);
5024
5025 r = new(char, l+1);
5026 if (!r)
5027 return NULL;
5028
5029 if (x) {
5030 p = stpcpy(r, x);
5031
5032 va_start(ap, x);
5033
5034 for (;;) {
5035 const char *t;
5036
5037 t = va_arg(ap, const char *);
5038 if (!t)
5039 break;
5040
5041 p = stpcpy(p, t);
5042 }
8ea913b2
LP
5043
5044 va_end(ap);
911a4828
LP
5045 } else
5046 r[0] = 0;
5047
5048 return r;
5049}
5050
b636465b
LP
5051bool is_main_thread(void) {
5052 static __thread int cached = 0;
5053
5054 if (_unlikely_(cached == 0))
5055 cached = getpid() == gettid() ? 1 : -1;
5056
5057 return cached > 0;
5058}
5059
94959f0f
LP
5060int block_get_whole_disk(dev_t d, dev_t *ret) {
5061 char *p, *s;
5062 int r;
5063 unsigned n, m;
5064
5065 assert(ret);
5066
5067 /* If it has a queue this is good enough for us */
5068 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
5069 return -ENOMEM;
5070
5071 r = access(p, F_OK);
5072 free(p);
5073
5074 if (r >= 0) {
5075 *ret = d;
5076 return 0;
5077 }
5078
5079 /* If it is a partition find the originating device */
5080 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
5081 return -ENOMEM;
5082
5083 r = access(p, F_OK);
5084 free(p);
5085
5086 if (r < 0)
5087 return -ENOENT;
5088
5089 /* Get parent dev_t */
5090 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
5091 return -ENOMEM;
5092
5093 r = read_one_line_file(p, &s);
5094 free(p);
5095
5096 if (r < 0)
5097 return r;
5098
5099 r = sscanf(s, "%u:%u", &m, &n);
5100 free(s);
5101
5102 if (r != 2)
5103 return -EINVAL;
5104
5105 /* Only return this if it is really good enough for us. */
5106 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
5107 return -ENOMEM;
5108
5109 r = access(p, F_OK);
5110 free(p);
5111
5112 if (r >= 0) {
5113 *ret = makedev(m, n);
5114 return 0;
5115 }
5116
5117 return -ENOENT;
5118}
5119
8d53b453 5120int file_is_priv_sticky(const char *p) {
ad293f5a
LP
5121 struct stat st;
5122
5123 assert(p);
5124
5125 if (lstat(p, &st) < 0)
5126 return -errno;
5127
5128 return
8d53b453 5129 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
5130 (st.st_mode & S_ISVTX);
5131}
94959f0f 5132
f41607a6
LP
5133static const char *const ioprio_class_table[] = {
5134 [IOPRIO_CLASS_NONE] = "none",
5135 [IOPRIO_CLASS_RT] = "realtime",
5136 [IOPRIO_CLASS_BE] = "best-effort",
5137 [IOPRIO_CLASS_IDLE] = "idle"
5138};
5139
5140DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5141
5142static const char *const sigchld_code_table[] = {
5143 [CLD_EXITED] = "exited",
5144 [CLD_KILLED] = "killed",
5145 [CLD_DUMPED] = "dumped",
5146 [CLD_TRAPPED] = "trapped",
5147 [CLD_STOPPED] = "stopped",
5148 [CLD_CONTINUED] = "continued",
5149};
5150
5151DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5152
5153static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5154 [LOG_FAC(LOG_KERN)] = "kern",
5155 [LOG_FAC(LOG_USER)] = "user",
5156 [LOG_FAC(LOG_MAIL)] = "mail",
5157 [LOG_FAC(LOG_DAEMON)] = "daemon",
5158 [LOG_FAC(LOG_AUTH)] = "auth",
5159 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5160 [LOG_FAC(LOG_LPR)] = "lpr",
5161 [LOG_FAC(LOG_NEWS)] = "news",
5162 [LOG_FAC(LOG_UUCP)] = "uucp",
5163 [LOG_FAC(LOG_CRON)] = "cron",
5164 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5165 [LOG_FAC(LOG_FTP)] = "ftp",
5166 [LOG_FAC(LOG_LOCAL0)] = "local0",
5167 [LOG_FAC(LOG_LOCAL1)] = "local1",
5168 [LOG_FAC(LOG_LOCAL2)] = "local2",
5169 [LOG_FAC(LOG_LOCAL3)] = "local3",
5170 [LOG_FAC(LOG_LOCAL4)] = "local4",
5171 [LOG_FAC(LOG_LOCAL5)] = "local5",
5172 [LOG_FAC(LOG_LOCAL6)] = "local6",
5173 [LOG_FAC(LOG_LOCAL7)] = "local7"
5174};
5175
5176DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5177
5178static const char *const log_level_table[] = {
5179 [LOG_EMERG] = "emerg",
5180 [LOG_ALERT] = "alert",
5181 [LOG_CRIT] = "crit",
5182 [LOG_ERR] = "err",
5183 [LOG_WARNING] = "warning",
5184 [LOG_NOTICE] = "notice",
5185 [LOG_INFO] = "info",
5186 [LOG_DEBUG] = "debug"
5187};
5188
5189DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5190
5191static const char* const sched_policy_table[] = {
5192 [SCHED_OTHER] = "other",
5193 [SCHED_BATCH] = "batch",
5194 [SCHED_IDLE] = "idle",
5195 [SCHED_FIFO] = "fifo",
5196 [SCHED_RR] = "rr"
5197};
5198
5199DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5200
5201static const char* const rlimit_table[] = {
5202 [RLIMIT_CPU] = "LimitCPU",
5203 [RLIMIT_FSIZE] = "LimitFSIZE",
5204 [RLIMIT_DATA] = "LimitDATA",
5205 [RLIMIT_STACK] = "LimitSTACK",
5206 [RLIMIT_CORE] = "LimitCORE",
5207 [RLIMIT_RSS] = "LimitRSS",
5208 [RLIMIT_NOFILE] = "LimitNOFILE",
5209 [RLIMIT_AS] = "LimitAS",
5210 [RLIMIT_NPROC] = "LimitNPROC",
5211 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5212 [RLIMIT_LOCKS] = "LimitLOCKS",
5213 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5214 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5215 [RLIMIT_NICE] = "LimitNICE",
5216 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5217 [RLIMIT_RTTIME] = "LimitRTTIME"
5218};
5219
5220DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5221
5222static const char* const ip_tos_table[] = {
5223 [IPTOS_LOWDELAY] = "low-delay",
5224 [IPTOS_THROUGHPUT] = "throughput",
5225 [IPTOS_RELIABILITY] = "reliability",
5226 [IPTOS_LOWCOST] = "low-cost",
5227};
5228
5229DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5230
4e240ab0 5231static const char *const __signal_table[] = {
f41607a6
LP
5232 [SIGHUP] = "HUP",
5233 [SIGINT] = "INT",
5234 [SIGQUIT] = "QUIT",
5235 [SIGILL] = "ILL",
5236 [SIGTRAP] = "TRAP",
5237 [SIGABRT] = "ABRT",
5238 [SIGBUS] = "BUS",
5239 [SIGFPE] = "FPE",
5240 [SIGKILL] = "KILL",
5241 [SIGUSR1] = "USR1",
5242 [SIGSEGV] = "SEGV",
5243 [SIGUSR2] = "USR2",
5244 [SIGPIPE] = "PIPE",
5245 [SIGALRM] = "ALRM",
5246 [SIGTERM] = "TERM",
5247#ifdef SIGSTKFLT
5248 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5249#endif
5250 [SIGCHLD] = "CHLD",
5251 [SIGCONT] = "CONT",
5252 [SIGSTOP] = "STOP",
5253 [SIGTSTP] = "TSTP",
5254 [SIGTTIN] = "TTIN",
5255 [SIGTTOU] = "TTOU",
5256 [SIGURG] = "URG",
5257 [SIGXCPU] = "XCPU",
5258 [SIGXFSZ] = "XFSZ",
5259 [SIGVTALRM] = "VTALRM",
5260 [SIGPROF] = "PROF",
5261 [SIGWINCH] = "WINCH",
5262 [SIGIO] = "IO",
5263 [SIGPWR] = "PWR",
5264 [SIGSYS] = "SYS"
5265};
5266
4e240ab0
MS
5267DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5268
5269const char *signal_to_string(int signo) {
5270 static __thread char buf[12];
5271 const char *name;
5272
5273 name = __signal_to_string(signo);
5274 if (name)
5275 return name;
5276
5277 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
5278 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
5279 else
5280 snprintf(buf, sizeof(buf) - 1, "%d", signo);
5281 char_array_0(buf);
5282 return buf;
5283}
5284
5285int signal_from_string(const char *s) {
5286 int signo;
5287 int offset = 0;
5288 unsigned u;
5289
5290 signo =__signal_from_string(s);
5291 if (signo > 0)
5292 return signo;
5293
5294 if (startswith(s, "RTMIN+")) {
5295 s += 6;
5296 offset = SIGRTMIN;
5297 }
5298 if (safe_atou(s, &u) >= 0) {
5299 signo = (int) u + offset;
5300 if (signo > 0 && signo < _NSIG)
5301 return signo;
5302 }
5303 return -1;
5304}
65457142
FC
5305
5306bool kexec_loaded(void) {
5307 bool loaded = false;
5308 char *s;
5309
5310 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5311 if (s[0] == '1')
5312 loaded = true;
5313 free(s);
5314 }
5315 return loaded;
5316}
fb9de93d
LP
5317
5318int strdup_or_null(const char *a, char **b) {
5319 char *c;
5320
5321 assert(b);
5322
5323 if (!a) {
5324 *b = NULL;
5325 return 0;
5326 }
5327
5328 c = strdup(a);
5329 if (!c)
5330 return -ENOMEM;
5331
5332 *b = c;
5333 return 0;
5334}
64685e0c 5335
87d2c1ff
LP
5336int prot_from_flags(int flags) {
5337
5338 switch (flags & O_ACCMODE) {
5339
5340 case O_RDONLY:
5341 return PROT_READ;
5342
5343 case O_WRONLY:
5344 return PROT_WRITE;
5345
5346 case O_RDWR:
5347 return PROT_READ|PROT_WRITE;
5348
5349 default:
5350 return -EINVAL;
5351 }
7c99e0c1 5352}
689b9a22 5353
babfc091 5354char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5355 unsigned i;
babfc091
LP
5356
5357 static const struct {
5358 const char *suffix;
5359 off_t factor;
5360 } table[] = {
32895bb3
LP
5361 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5362 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5363 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5364 { "G", 1024ULL*1024ULL*1024ULL },
5365 { "M", 1024ULL*1024ULL },
5366 { "K", 1024ULL },
5367 };
5368
5369 for (i = 0; i < ELEMENTSOF(table); i++) {
5370
5371 if (t >= table[i].factor) {
5372 snprintf(buf, l,
5373 "%llu.%llu%s",
5374 (unsigned long long) (t / table[i].factor),
5375 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5376 table[i].suffix);
5377
5378 goto finish;
5379 }
5380 }
5381
5382 snprintf(buf, l, "%lluB", (unsigned long long) t);
5383
5384finish:
5385 buf[l-1] = 0;
5386 return buf;
5387
5388}
55d7bfc1
LP
5389
5390void* memdup(const void *p, size_t l) {
5391 void *r;
5392
5393 assert(p);
5394
5395 r = malloc(l);
5396 if (!r)
5397 return NULL;
5398
5399 memcpy(r, p, l);
5400 return r;
5401}
bb99a35a
LP
5402
5403int fd_inc_sndbuf(int fd, size_t n) {
5404 int r, value;
5405 socklen_t l = sizeof(value);
5406
5407 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
5408 if (r >= 0 &&
5409 l == sizeof(value) &&
5410 (size_t) value >= n*2)
5411 return 0;
5412
5413 value = (int) n;
5414 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
5415 if (r < 0)
5416 return -errno;
5417
5418 return 1;
5419}
5420
5421int fd_inc_rcvbuf(int fd, size_t n) {
5422 int r, value;
5423 socklen_t l = sizeof(value);
5424
5425 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
5426 if (r >= 0 &&
5427 l == sizeof(value) &&
5428 (size_t) value >= n*2)
5429 return 0;
5430
5431 value = (int) n;
5432 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
5433 if (r < 0)
5434 return -errno;
5435
5436 return 1;
5437}
6bb92a16 5438
9bdc770c 5439int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
5440 pid_t parent_pid, agent_pid;
5441 int fd;
5442 bool stdout_is_tty, stderr_is_tty;
5443 unsigned n, i;
5444 va_list ap;
5445 char **l;
5446
5447 assert(pid);
5448 assert(path);
5449
5450 parent_pid = getpid();
5451
5452 /* Spawns a temporary TTY agent, making sure it goes away when
5453 * we go away */
5454
5455 agent_pid = fork();
5456 if (agent_pid < 0)
5457 return -errno;
5458
5459 if (agent_pid != 0) {
5460 *pid = agent_pid;
5461 return 0;
5462 }
5463
5464 /* In the child:
5465 *
5466 * Make sure the agent goes away when the parent dies */
5467 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5468 _exit(EXIT_FAILURE);
5469
5470 /* Check whether our parent died before we were able
5471 * to set the death signal */
5472 if (getppid() != parent_pid)
5473 _exit(EXIT_SUCCESS);
5474
5475 /* Don't leak fds to the agent */
9bdc770c 5476 close_all_fds(except, n_except);
6bb92a16
LP
5477
5478 stdout_is_tty = isatty(STDOUT_FILENO);
5479 stderr_is_tty = isatty(STDERR_FILENO);
5480
5481 if (!stdout_is_tty || !stderr_is_tty) {
5482 /* Detach from stdout/stderr. and reopen
5483 * /dev/tty for them. This is important to
5484 * ensure that when systemctl is started via
5485 * popen() or a similar call that expects to
5486 * read EOF we actually do generate EOF and
5487 * not delay this indefinitely by because we
5488 * keep an unused copy of stdin around. */
5489 fd = open("/dev/tty", O_WRONLY);
5490 if (fd < 0) {
5491 log_error("Failed to open /dev/tty: %m");
5492 _exit(EXIT_FAILURE);
5493 }
5494
5495 if (!stdout_is_tty)
5496 dup2(fd, STDOUT_FILENO);
5497
5498 if (!stderr_is_tty)
5499 dup2(fd, STDERR_FILENO);
5500
5501 if (fd > 2)
5502 close(fd);
5503 }
5504
5505 /* Count arguments */
5506 va_start(ap, path);
5507 for (n = 0; va_arg(ap, char*); n++)
5508 ;
5509 va_end(ap);
5510
5511 /* Allocate strv */
5512 l = alloca(sizeof(char *) * (n + 1));
5513
5514 /* Fill in arguments */
5515 va_start(ap, path);
5516 for (i = 0; i <= n; i++)
5517 l[i] = va_arg(ap, char*);
5518 va_end(ap);
5519
5520 execv(path, l);
5521 _exit(EXIT_FAILURE);
5522}
68faf98c
LP
5523
5524int setrlimit_closest(int resource, const struct rlimit *rlim) {
5525 struct rlimit highest, fixed;
5526
5527 assert(rlim);
5528
5529 if (setrlimit(resource, rlim) >= 0)
5530 return 0;
5531
5532 if (errno != EPERM)
5533 return -errno;
5534
5535 /* So we failed to set the desired setrlimit, then let's try
5536 * to get as close as we can */
5537 assert_se(getrlimit(resource, &highest) == 0);
5538
5539 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5540 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5541
5542 if (setrlimit(resource, &fixed) < 0)
5543 return -errno;
5544
5545 return 0;
5546}
3d9a4122 5547
ab94af92
LP
5548int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5549 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5550 int r;
5551 FILE *f;
5552 bool done = false;
5553 size_t l;
5554
5555 assert(field);
5556 assert(_value);
5557
5558 if (pid == 0)
5559 pid = getpid();
5560
5561 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5562 char_array_0(path);
5563
5564 f = fopen(path, "re");
5565 if (!f)
5566 return -errno;
5567
5568 l = strlen(field);
5569 r = 0;
5570
5571 do {
5572 char line[LINE_MAX];
5573 unsigned i;
5574
5575 for (i = 0; i < sizeof(line)-1; i++) {
5576 int c;
5577
5578 c = getc(f);
5579 if (_unlikely_(c == EOF)) {
5580 done = true;
5581 break;
5582 } else if (c == 0)
5583 break;
5584
5585 line[i] = c;
5586 }
5587 line[i] = 0;
5588
5589 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5590 value = strdup(line + l + 1);
5591 if (!value) {
5592 r = -ENOMEM;
5593 break;
5594 }
5595
5596 r = 1;
5597 break;
5598 }
5599
5600 } while (!done);
5601
5602 fclose(f);
5603
5604 if (r >= 0)
5605 *_value = value;
5606
5607 return r;
5608}
d889a206
LP
5609
5610int can_sleep(const char *type) {
5611 char *p, *w, *state;
5612 size_t l, k;
5613 bool found = false;
5614 int r;
5615
5616 assert(type);
5617
5618 r = read_one_line_file("/sys/power/state", &p);
5619 if (r < 0)
5620 return r == -ENOENT ? 0 : r;
5621
5622 k = strlen(type);
5623
5624 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
5625 if (l == k && strncmp(w, type, l) == 0) {
5626 found = true;
5627 break;
5628 }
5629 }
5630
5631 free(p);
5632 return found;
5633}
49dbfa7b
LP
5634
5635bool is_valid_documentation_url(const char *url) {
5636 assert(url);
5637
5638 if (startswith(url, "http://") && url[7])
5639 return true;
5640
5641 if (startswith(url, "https://") && url[8])
5642 return true;
5643
5644 if (startswith(url, "file:") && url[5])
5645 return true;
5646
5647 if (startswith(url, "info:") && url[5])
5648 return true;
5649
5650 if (startswith(url, "man:") && url[4])
5651 return true;
5652
5653 return false;
5654}
9be346c9
HH
5655
5656bool in_initrd(void) {
5657 static bool checked=false;
5658 static bool is_in_initrd=false;
5659
5660 if (!checked) {
5661 struct stat sb;
5662 if (stat("/", &sb) == 0) {
5663 is_in_initrd = (sb.st_dev == 1);
5664 checked = true;
5665 }
5666 }
5667
5668 return is_in_initrd;
5669}