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