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