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