]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
journal: fix potential integer overflow
[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
LP
74
75static int parsed_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
LP
2178 bool on_tty;
2179
80876c20
LP
2180 assert(ret);
2181 assert(replies);
2182 assert(text);
2183
1b39d4b9
LP
2184 on_tty = isatty(STDOUT_FILENO);
2185
80876c20
LP
2186 for (;;) {
2187 va_list ap;
2188 char c;
2189 int r;
2190 bool need_nl = true;
2191
1b39d4b9 2192 if (on_tty)
c1072ea0 2193 fputs(ANSI_HIGHLIGHT_ON, stdout);
b1b2dc0c 2194
80876c20
LP
2195 va_start(ap, text);
2196 vprintf(text, ap);
2197 va_end(ap);
2198
1b39d4b9 2199 if (on_tty)
c1072ea0 2200 fputs(ANSI_HIGHLIGHT_OFF, stdout);
b1b2dc0c 2201
80876c20
LP
2202 fflush(stdout);
2203
8f2d43a0
LP
2204 r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
2205 if (r < 0) {
80876c20
LP
2206
2207 if (r == -EBADMSG) {
2208 puts("Bad input, please try again.");
2209 continue;
2210 }
2211
2212 putchar('\n');
2213 return r;
2214 }
2215
2216 if (need_nl)
2217 putchar('\n');
2218
2219 if (strchr(replies, c)) {
2220 *ret = c;
2221 return 0;
2222 }
2223
2224 puts("Read unexpected character, please try again.");
2225 }
2226}
2227
512947d4 2228int reset_terminal_fd(int fd, bool switch_to_text) {
80876c20
LP
2229 struct termios termios;
2230 int r = 0;
3fe5e5d4
LP
2231
2232 /* Set terminal to some sane defaults */
80876c20
LP
2233
2234 assert(fd >= 0);
2235
eed1d0e3
LP
2236 /* We leave locked terminal attributes untouched, so that
2237 * Plymouth may set whatever it wants to set, and we don't
2238 * interfere with that. */
3fe5e5d4
LP
2239
2240 /* Disable exclusive mode, just in case */
2241 ioctl(fd, TIOCNXCL);
2242
5c0100a5 2243 /* Switch to text mode */
512947d4
MS
2244 if (switch_to_text)
2245 ioctl(fd, KDSETMODE, KD_TEXT);
5c0100a5 2246
3fe5e5d4 2247 /* Enable console unicode mode */
df465b3f 2248 ioctl(fd, KDSKBMODE, K_UNICODE);
80876c20
LP
2249
2250 if (tcgetattr(fd, &termios) < 0) {
2251 r = -errno;
2252 goto finish;
2253 }
2254
aaf694ca
LP
2255 /* We only reset the stuff that matters to the software. How
2256 * hardware is set up we don't touch assuming that somebody
2257 * else will do that for us */
2258
2259 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
2260 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
2261 termios.c_oflag |= ONLCR;
2262 termios.c_cflag |= CREAD;
2263 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
2264
2265 termios.c_cc[VINTR] = 03; /* ^C */
2266 termios.c_cc[VQUIT] = 034; /* ^\ */
2267 termios.c_cc[VERASE] = 0177;
2268 termios.c_cc[VKILL] = 025; /* ^X */
2269 termios.c_cc[VEOF] = 04; /* ^D */
2270 termios.c_cc[VSTART] = 021; /* ^Q */
2271 termios.c_cc[VSTOP] = 023; /* ^S */
2272 termios.c_cc[VSUSP] = 032; /* ^Z */
2273 termios.c_cc[VLNEXT] = 026; /* ^V */
2274 termios.c_cc[VWERASE] = 027; /* ^W */
2275 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
2276 termios.c_cc[VEOL] = 0;
2277 termios.c_cc[VEOL2] = 0;
80876c20
LP
2278
2279 termios.c_cc[VTIME] = 0;
2280 termios.c_cc[VMIN] = 1;
2281
2282 if (tcsetattr(fd, TCSANOW, &termios) < 0)
2283 r = -errno;
2284
2285finish:
2286 /* Just in case, flush all crap out */
2287 tcflush(fd, TCIOFLUSH);
2288
2289 return r;
2290}
2291
6ea832a2
LP
2292int reset_terminal(const char *name) {
2293 int fd, r;
2294
2295 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
2296 if (fd < 0)
2297 return fd;
2298
512947d4 2299 r = reset_terminal_fd(fd, true);
6ea832a2
LP
2300 close_nointr_nofail(fd);
2301
2302 return r;
2303}
2304
80876c20
LP
2305int open_terminal(const char *name, int mode) {
2306 int fd, r;
f73f76ac 2307 unsigned c = 0;
80876c20 2308
f73f76ac
LP
2309 /*
2310 * If a TTY is in the process of being closed opening it might
2311 * cause EIO. This is horribly awful, but unlikely to be
2312 * changed in the kernel. Hence we work around this problem by
2313 * retrying a couple of times.
2314 *
2315 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
2316 */
2317
2318 for (;;) {
af6da548
LP
2319 fd = open(name, mode);
2320 if (fd >= 0)
f73f76ac
LP
2321 break;
2322
2323 if (errno != EIO)
2324 return -errno;
2325
af6da548 2326 /* Max 1s in total */
f73f76ac
LP
2327 if (c >= 20)
2328 return -errno;
2329
2330 usleep(50 * USEC_PER_MSEC);
2331 c++;
2332 }
2333
2334 if (fd < 0)
80876c20
LP
2335 return -errno;
2336
af6da548
LP
2337 r = isatty(fd);
2338 if (r < 0) {
80876c20
LP
2339 close_nointr_nofail(fd);
2340 return -errno;
2341 }
2342
2343 if (!r) {
2344 close_nointr_nofail(fd);
2345 return -ENOTTY;
2346 }
2347
2348 return fd;
2349}
2350
2351int flush_fd(int fd) {
2352 struct pollfd pollfd;
2353
2354 zero(pollfd);
2355 pollfd.fd = fd;
2356 pollfd.events = POLLIN;
2357
2358 for (;;) {
20c03b7b 2359 char buf[LINE_MAX];
80876c20
LP
2360 ssize_t l;
2361 int r;
2362
2363 if ((r = poll(&pollfd, 1, 0)) < 0) {
2364
2365 if (errno == EINTR)
2366 continue;
2367
2368 return -errno;
2369 }
2370
2371 if (r == 0)
2372 return 0;
2373
2374 if ((l = read(fd, buf, sizeof(buf))) < 0) {
2375
2376 if (errno == EINTR)
2377 continue;
2378
2379 if (errno == EAGAIN)
2380 return 0;
2381
2382 return -errno;
2383 }
2384
2385 if (l <= 0)
2386 return 0;
2387 }
2388}
2389
af6da548
LP
2390int acquire_terminal(
2391 const char *name,
2392 bool fail,
2393 bool force,
2394 bool ignore_tiocstty_eperm,
2395 usec_t timeout) {
2396
4a0ff478 2397 int fd = -1, notify = -1, r = 0, wd = -1;
af6da548 2398 usec_t ts = 0;
32c4bef8 2399 struct sigaction sa_old, sa_new;
80876c20
LP
2400
2401 assert(name);
2402
2403 /* We use inotify to be notified when the tty is closed. We
2404 * create the watch before checking if we can actually acquire
2405 * it, so that we don't lose any event.
2406 *
2407 * Note: strictly speaking this actually watches for the
2408 * device being closed, it does *not* really watch whether a
2409 * tty loses its controlling process. However, unless some
2410 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
2411 * its tty otherwise this will not become a problem. As long
2412 * as the administrator makes sure not configure any service
2413 * on the same tty as an untrusted user this should not be a
2414 * problem. (Which he probably should not do anyway.) */
2415
af6da548
LP
2416 if (timeout != (usec_t) -1)
2417 ts = now(CLOCK_MONOTONIC);
2418
80876c20 2419 if (!fail && !force) {
af6da548
LP
2420 notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
2421 if (notify < 0) {
80876c20
LP
2422 r = -errno;
2423 goto fail;
2424 }
2425
af6da548
LP
2426 wd = inotify_add_watch(notify, name, IN_CLOSE);
2427 if (wd < 0) {
80876c20
LP
2428 r = -errno;
2429 goto fail;
2430 }
2431 }
2432
2433 for (;;) {
af6da548
LP
2434 if (notify >= 0) {
2435 r = flush_fd(notify);
2436 if (r < 0)
e3d1855b 2437 goto fail;
af6da548 2438 }
80876c20
LP
2439
2440 /* We pass here O_NOCTTY only so that we can check the return
2441 * value TIOCSCTTY and have a reliable way to figure out if we
2442 * successfully became the controlling process of the tty */
af6da548
LP
2443 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
2444 if (fd < 0)
6ea832a2 2445 return fd;
80876c20 2446
32c4bef8
LP
2447 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2448 * if we already own the tty. */
2449 zero(sa_new);
2450 sa_new.sa_handler = SIG_IGN;
2451 sa_new.sa_flags = SA_RESTART;
2452 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2453
80876c20 2454 /* First, try to get the tty */
32c4bef8
LP
2455 if (ioctl(fd, TIOCSCTTY, force) < 0)
2456 r = -errno;
2457
2458 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
21de3988
LP
2459
2460 /* Sometimes it makes sense to ignore TIOCSCTTY
2461 * returning EPERM, i.e. when very likely we already
2462 * are have this controlling terminal. */
32c4bef8 2463 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
21de3988
LP
2464 r = 0;
2465
32c4bef8 2466 if (r < 0 && (force || fail || r != -EPERM)) {
80876c20
LP
2467 goto fail;
2468 }
2469
2470 if (r >= 0)
2471 break;
2472
2473 assert(!fail);
2474 assert(!force);
2475 assert(notify >= 0);
2476
2477 for (;;) {
f601daa7 2478 uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
80876c20 2479 ssize_t l;
f601daa7 2480 struct inotify_event *e;
80876c20 2481
af6da548
LP
2482 if (timeout != (usec_t) -1) {
2483 usec_t n;
2484
2485 n = now(CLOCK_MONOTONIC);
2486 if (ts + timeout < n) {
2487 r = -ETIMEDOUT;
2488 goto fail;
2489 }
2490
2491 r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
2492 if (r < 0)
2493 goto fail;
2494
2495 if (r == 0) {
2496 r = -ETIMEDOUT;
2497 goto fail;
2498 }
2499 }
2500
2501 l = read(notify, inotify_buffer, sizeof(inotify_buffer));
2502 if (l < 0) {
80876c20 2503
af6da548 2504 if (errno == EINTR || errno == EAGAIN)
f601daa7
LP
2505 continue;
2506
2507 r = -errno;
2508 goto fail;
2509 }
2510
2511 e = (struct inotify_event*) inotify_buffer;
80876c20 2512
f601daa7
LP
2513 while (l > 0) {
2514 size_t step;
80876c20 2515
f601daa7 2516 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
80876c20 2517 r = -EIO;
f601daa7
LP
2518 goto fail;
2519 }
80876c20 2520
f601daa7
LP
2521 step = sizeof(struct inotify_event) + e->len;
2522 assert(step <= (size_t) l);
80876c20 2523
f601daa7
LP
2524 e = (struct inotify_event*) ((uint8_t*) e + step);
2525 l -= step;
80876c20
LP
2526 }
2527
2528 break;
2529 }
2530
2531 /* We close the tty fd here since if the old session
2532 * ended our handle will be dead. It's important that
2533 * we do this after sleeping, so that we don't enter
2534 * an endless loop. */
2535 close_nointr_nofail(fd);
2536 }
2537
2538 if (notify >= 0)
a16e1123 2539 close_nointr_nofail(notify);
80876c20 2540
512947d4
MS
2541 r = reset_terminal_fd(fd, true);
2542 if (r < 0)
80876c20
LP
2543 log_warning("Failed to reset terminal: %s", strerror(-r));
2544
2545 return fd;
2546
2547fail:
2548 if (fd >= 0)
a16e1123 2549 close_nointr_nofail(fd);
80876c20
LP
2550
2551 if (notify >= 0)
a16e1123 2552 close_nointr_nofail(notify);
80876c20
LP
2553
2554 return r;
2555}
2556
2557int release_terminal(void) {
2558 int r = 0, fd;
57cd2192 2559 struct sigaction sa_old, sa_new;
80876c20 2560
ccaa6149 2561 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
80876c20
LP
2562 return -errno;
2563
57cd2192
LP
2564 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2565 * by our own TIOCNOTTY */
2566
2567 zero(sa_new);
2568 sa_new.sa_handler = SIG_IGN;
2569 sa_new.sa_flags = SA_RESTART;
2570 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2571
80876c20
LP
2572 if (ioctl(fd, TIOCNOTTY) < 0)
2573 r = -errno;
2574
57cd2192
LP
2575 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
2576
80876c20
LP
2577 close_nointr_nofail(fd);
2578 return r;
2579}
2580
9a34ec5f
LP
2581int sigaction_many(const struct sigaction *sa, ...) {
2582 va_list ap;
2583 int r = 0, sig;
2584
2585 va_start(ap, sa);
2586 while ((sig = va_arg(ap, int)) > 0)
2587 if (sigaction(sig, sa, NULL) < 0)
2588 r = -errno;
2589 va_end(ap);
2590
2591 return r;
2592}
2593
2594int ignore_signals(int sig, ...) {
a337c6fc 2595 struct sigaction sa;
9a34ec5f
LP
2596 va_list ap;
2597 int r = 0;
a337c6fc
LP
2598
2599 zero(sa);
2600 sa.sa_handler = SIG_IGN;
2601 sa.sa_flags = SA_RESTART;
2602
9a34ec5f
LP
2603 if (sigaction(sig, &sa, NULL) < 0)
2604 r = -errno;
2605
2606 va_start(ap, sig);
2607 while ((sig = va_arg(ap, int)) > 0)
2608 if (sigaction(sig, &sa, NULL) < 0)
2609 r = -errno;
2610 va_end(ap);
2611
2612 return r;
2613}
2614
2615int default_signals(int sig, ...) {
2616 struct sigaction sa;
2617 va_list ap;
2618 int r = 0;
2619
2620 zero(sa);
2621 sa.sa_handler = SIG_DFL;
2622 sa.sa_flags = SA_RESTART;
2623
2624 if (sigaction(sig, &sa, NULL) < 0)
2625 r = -errno;
2626
2627 va_start(ap, sig);
2628 while ((sig = va_arg(ap, int)) > 0)
2629 if (sigaction(sig, &sa, NULL) < 0)
2630 r = -errno;
2631 va_end(ap);
2632
2633 return r;
a337c6fc
LP
2634}
2635
8d567588
LP
2636int close_pipe(int p[]) {
2637 int a = 0, b = 0;
2638
2639 assert(p);
2640
2641 if (p[0] >= 0) {
2642 a = close_nointr(p[0]);
2643 p[0] = -1;
2644 }
2645
2646 if (p[1] >= 0) {
2647 b = close_nointr(p[1]);
2648 p[1] = -1;
2649 }
2650
2651 return a < 0 ? a : b;
2652}
2653
eb22ac37 2654ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
8d567588
LP
2655 uint8_t *p;
2656 ssize_t n = 0;
2657
2658 assert(fd >= 0);
2659 assert(buf);
2660
2661 p = buf;
2662
2663 while (nbytes > 0) {
2664 ssize_t k;
2665
2666 if ((k = read(fd, p, nbytes)) <= 0) {
2667
eb22ac37 2668 if (k < 0 && errno == EINTR)
8d567588
LP
2669 continue;
2670
eb22ac37 2671 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588
LP
2672 struct pollfd pollfd;
2673
2674 zero(pollfd);
2675 pollfd.fd = fd;
2676 pollfd.events = POLLIN;
2677
2678 if (poll(&pollfd, 1, -1) < 0) {
2679 if (errno == EINTR)
2680 continue;
2681
2682 return n > 0 ? n : -errno;
2683 }
2684
2685 if (pollfd.revents != POLLIN)
2686 return n > 0 ? n : -EIO;
2687
2688 continue;
2689 }
2690
2691 return n > 0 ? n : (k < 0 ? -errno : 0);
2692 }
2693
2694 p += k;
2695 nbytes -= k;
2696 n += k;
2697 }
2698
2699 return n;
2700}
2701
eb22ac37
LP
2702ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2703 const uint8_t *p;
2704 ssize_t n = 0;
2705
2706 assert(fd >= 0);
2707 assert(buf);
2708
2709 p = buf;
2710
2711 while (nbytes > 0) {
2712 ssize_t k;
2713
fe652127
LP
2714 k = write(fd, p, nbytes);
2715 if (k <= 0) {
eb22ac37
LP
2716
2717 if (k < 0 && errno == EINTR)
2718 continue;
2719
2720 if (k < 0 && errno == EAGAIN && do_poll) {
2721 struct pollfd pollfd;
2722
2723 zero(pollfd);
2724 pollfd.fd = fd;
2725 pollfd.events = POLLOUT;
2726
2727 if (poll(&pollfd, 1, -1) < 0) {
2728 if (errno == EINTR)
2729 continue;
2730
2731 return n > 0 ? n : -errno;
2732 }
2733
2734 if (pollfd.revents != POLLOUT)
2735 return n > 0 ? n : -EIO;
2736
2737 continue;
2738 }
2739
2740 return n > 0 ? n : (k < 0 ? -errno : 0);
2741 }
2742
2743 p += k;
2744 nbytes -= k;
2745 n += k;
2746 }
2747
2748 return n;
2749}
2750
24a6e4a4
LP
2751int parse_usec(const char *t, usec_t *usec) {
2752 static const struct {
2753 const char *suffix;
2754 usec_t usec;
2755 } table[] = {
cfbc22ab
LP
2756 { "seconds", USEC_PER_SEC },
2757 { "second", USEC_PER_SEC },
24a6e4a4
LP
2758 { "sec", USEC_PER_SEC },
2759 { "s", USEC_PER_SEC },
cfbc22ab
LP
2760 { "minutes", USEC_PER_MINUTE },
2761 { "minute", USEC_PER_MINUTE },
24a6e4a4 2762 { "min", USEC_PER_MINUTE },
cfbc22ab
LP
2763 { "months", USEC_PER_MONTH },
2764 { "month", USEC_PER_MONTH },
2765 { "msec", USEC_PER_MSEC },
2766 { "ms", USEC_PER_MSEC },
2767 { "m", USEC_PER_MINUTE },
2768 { "hours", USEC_PER_HOUR },
2769 { "hour", USEC_PER_HOUR },
24a6e4a4
LP
2770 { "hr", USEC_PER_HOUR },
2771 { "h", USEC_PER_HOUR },
cfbc22ab
LP
2772 { "days", USEC_PER_DAY },
2773 { "day", USEC_PER_DAY },
24a6e4a4 2774 { "d", USEC_PER_DAY },
cfbc22ab
LP
2775 { "weeks", USEC_PER_WEEK },
2776 { "week", USEC_PER_WEEK },
24a6e4a4 2777 { "w", USEC_PER_WEEK },
cfbc22ab
LP
2778 { "years", USEC_PER_YEAR },
2779 { "year", USEC_PER_YEAR },
2780 { "y", USEC_PER_YEAR },
24a6e4a4
LP
2781 { "usec", 1ULL },
2782 { "us", 1ULL },
d88a251b 2783 { "", USEC_PER_SEC }, /* default is sec */
24a6e4a4
LP
2784 };
2785
2786 const char *p;
2787 usec_t r = 0;
2788
2789 assert(t);
2790 assert(usec);
2791
2792 p = t;
2793 do {
2794 long long l;
2795 char *e;
2796 unsigned i;
2797
2798 errno = 0;
2799 l = strtoll(p, &e, 10);
2800
2801 if (errno != 0)
2802 return -errno;
2803
2804 if (l < 0)
2805 return -ERANGE;
2806
2807 if (e == p)
2808 return -EINVAL;
2809
2810 e += strspn(e, WHITESPACE);
2811
2812 for (i = 0; i < ELEMENTSOF(table); i++)
2813 if (startswith(e, table[i].suffix)) {
2814 r += (usec_t) l * table[i].usec;
2815 p = e + strlen(table[i].suffix);
2816 break;
2817 }
2818
2819 if (i >= ELEMENTSOF(table))
2820 return -EINVAL;
2821
2822 } while (*p != 0);
2823
2824 *usec = r;
2825
2826 return 0;
2827}
2828
d88a251b
LP
2829int parse_nsec(const char *t, nsec_t *nsec) {
2830 static const struct {
2831 const char *suffix;
2832 nsec_t nsec;
2833 } table[] = {
cfbc22ab
LP
2834 { "seconds", NSEC_PER_SEC },
2835 { "second", NSEC_PER_SEC },
d88a251b
LP
2836 { "sec", NSEC_PER_SEC },
2837 { "s", NSEC_PER_SEC },
cfbc22ab
LP
2838 { "minutes", NSEC_PER_MINUTE },
2839 { "minute", NSEC_PER_MINUTE },
d88a251b 2840 { "min", NSEC_PER_MINUTE },
cfbc22ab
LP
2841 { "months", NSEC_PER_MONTH },
2842 { "month", NSEC_PER_MONTH },
2843 { "msec", NSEC_PER_MSEC },
2844 { "ms", NSEC_PER_MSEC },
2845 { "m", NSEC_PER_MINUTE },
2846 { "hours", NSEC_PER_HOUR },
2847 { "hour", NSEC_PER_HOUR },
d88a251b
LP
2848 { "hr", NSEC_PER_HOUR },
2849 { "h", NSEC_PER_HOUR },
cfbc22ab
LP
2850 { "days", NSEC_PER_DAY },
2851 { "day", NSEC_PER_DAY },
d88a251b 2852 { "d", NSEC_PER_DAY },
cfbc22ab
LP
2853 { "weeks", NSEC_PER_WEEK },
2854 { "week", NSEC_PER_WEEK },
d88a251b 2855 { "w", NSEC_PER_WEEK },
cfbc22ab
LP
2856 { "years", NSEC_PER_YEAR },
2857 { "year", NSEC_PER_YEAR },
2858 { "y", NSEC_PER_YEAR },
d88a251b
LP
2859 { "usec", NSEC_PER_USEC },
2860 { "us", NSEC_PER_USEC },
2861 { "nsec", 1ULL },
2862 { "ns", 1ULL },
2863 { "", 1ULL }, /* default is nsec */
2864 };
2865
2866 const char *p;
2867 nsec_t r = 0;
2868
2869 assert(t);
2870 assert(nsec);
2871
2872 p = t;
2873 do {
2874 long long l;
2875 char *e;
2876 unsigned i;
2877
2878 errno = 0;
2879 l = strtoll(p, &e, 10);
2880
2881 if (errno != 0)
2882 return -errno;
2883
2884 if (l < 0)
2885 return -ERANGE;
2886
2887 if (e == p)
2888 return -EINVAL;
2889
2890 e += strspn(e, WHITESPACE);
2891
2892 for (i = 0; i < ELEMENTSOF(table); i++)
2893 if (startswith(e, table[i].suffix)) {
2894 r += (nsec_t) l * table[i].nsec;
2895 p = e + strlen(table[i].suffix);
2896 break;
2897 }
2898
2899 if (i >= ELEMENTSOF(table))
2900 return -EINVAL;
2901
2902 } while (*p != 0);
2903
2904 *nsec = r;
2905
2906 return 0;
2907}
2908
ab1f0633
LP
2909int parse_bytes(const char *t, off_t *bytes) {
2910 static const struct {
2911 const char *suffix;
2912 off_t factor;
2913 } table[] = {
2914 { "B", 1 },
2915 { "K", 1024ULL },
2916 { "M", 1024ULL*1024ULL },
2917 { "G", 1024ULL*1024ULL*1024ULL },
2918 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
32895bb3
LP
2919 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2920 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
ab1f0633
LP
2921 { "", 1 },
2922 };
2923
2924 const char *p;
2925 off_t r = 0;
2926
2927 assert(t);
2928 assert(bytes);
2929
2930 p = t;
2931 do {
2932 long long l;
2933 char *e;
2934 unsigned i;
2935
2936 errno = 0;
2937 l = strtoll(p, &e, 10);
2938
2939 if (errno != 0)
2940 return -errno;
2941
2942 if (l < 0)
2943 return -ERANGE;
2944
2945 if (e == p)
2946 return -EINVAL;
2947
2948 e += strspn(e, WHITESPACE);
2949
2950 for (i = 0; i < ELEMENTSOF(table); i++)
2951 if (startswith(e, table[i].suffix)) {
2952 r += (off_t) l * table[i].factor;
2953 p = e + strlen(table[i].suffix);
2954 break;
2955 }
2956
2957 if (i >= ELEMENTSOF(table))
2958 return -EINVAL;
2959
2960 } while (*p != 0);
2961
2962 *bytes = r;
2963
2964 return 0;
2965}
2966
843d2643
LP
2967int make_stdio(int fd) {
2968 int r, s, t;
2969
2970 assert(fd >= 0);
2971
73836c5c
LP
2972 r = dup3(fd, STDIN_FILENO, 0);
2973 s = dup3(fd, STDOUT_FILENO, 0);
2974 t = dup3(fd, STDERR_FILENO, 0);
843d2643
LP
2975
2976 if (fd >= 3)
2977 close_nointr_nofail(fd);
2978
2979 if (r < 0 || s < 0 || t < 0)
2980 return -errno;
2981
73836c5c 2982 /* We rely here that the new fd has O_CLOEXEC not set */
7862f62d 2983
843d2643
LP
2984 return 0;
2985}
2986
ade509ce
LP
2987int make_null_stdio(void) {
2988 int null_fd;
2989
cd3bd60a
LP
2990 null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
2991 if (null_fd < 0)
ade509ce
LP
2992 return -errno;
2993
2994 return make_stdio(null_fd);
2995}
2996
8407a5d0
LP
2997bool is_device_path(const char *path) {
2998
2999 /* Returns true on paths that refer to a device, either in
3000 * sysfs or in /dev */
3001
3002 return
3003 path_startswith(path, "/dev/") ||
3004 path_startswith(path, "/sys/");
3005}
3006
01f78473 3007int dir_is_empty(const char *path) {
a05f97b3 3008 _cleanup_closedir_ DIR *d;
01f78473 3009 int r;
01f78473 3010
a05f97b3
LP
3011 d = opendir(path);
3012 if (!d)
01f78473
LP
3013 return -errno;
3014
3015 for (;;) {
7d5e9c0f
LP
3016 struct dirent *de;
3017 union dirent_storage buf;
01f78473 3018
7d5e9c0f 3019 r = readdir_r(d, &buf.de, &de);
a05f97b3
LP
3020 if (r > 0)
3021 return -r;
01f78473 3022
a05f97b3
LP
3023 if (!de)
3024 return 1;
01f78473 3025
a05f97b3
LP
3026 if (!ignore_file(de->d_name))
3027 return 0;
3028 }
01f78473
LP
3029}
3030
d3782d60 3031unsigned long long random_ull(void) {
a05f97b3 3032 _cleanup_close_ int fd;
d3782d60
LP
3033 uint64_t ull;
3034 ssize_t r;
3035
ac0930c8
LP
3036 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
3037 if (fd < 0)
d3782d60
LP
3038 goto fallback;
3039
eb22ac37 3040 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
3041 if (r != sizeof(ull))
3042 goto fallback;
3043
3044 return ull;
3045
3046fallback:
3047 return random() * RAND_MAX + random();
3048}
3049
5b6319dc
LP
3050void rename_process(const char name[8]) {
3051 assert(name);
3052
5d6b1584
LP
3053 /* This is a like a poor man's setproctitle(). It changes the
3054 * comm field, argv[0], and also the glibc's internally used
3055 * name of the process. For the first one a limit of 16 chars
3056 * applies, to the second one usually one of 10 (i.e. length
3057 * of "/sbin/init"), to the third one one of 7 (i.e. length of
3058 * "systemd"). If you pass a longer string it will be
3059 * truncated */
5b6319dc 3060
5d6b1584 3061 prctl(PR_SET_NAME, name);
5b6319dc
LP
3062
3063 if (program_invocation_name)
3064 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
3065
3066 if (saved_argc > 0) {
3067 int i;
3068
3069 if (saved_argv[0])
3070 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
3071
3072 for (i = 1; i < saved_argc; i++) {
3073 if (!saved_argv[i])
3074 break;
3075
3076 memset(saved_argv[i], 0, strlen(saved_argv[i]));
3077 }
3078 }
5b6319dc
LP
3079}
3080
7d793605
LP
3081void sigset_add_many(sigset_t *ss, ...) {
3082 va_list ap;
3083 int sig;
3084
3085 assert(ss);
3086
3087 va_start(ap, ss);
3088 while ((sig = va_arg(ap, int)) > 0)
3089 assert_se(sigaddset(ss, sig) == 0);
3090 va_end(ap);
3091}
3092
ef2f1067
LP
3093char* gethostname_malloc(void) {
3094 struct utsname u;
3095
3096 assert_se(uname(&u) >= 0);
3097
344de609 3098 if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
ef2f1067
LP
3099 return strdup(u.nodename);
3100
3101 return strdup(u.sysname);
3102}
3103
344de609
LP
3104bool hostname_is_set(void) {
3105 struct utsname u;
3106
3107 assert_se(uname(&u) >= 0);
3108
3109 return !isempty(u.nodename) && !streq(u.nodename, "(none)");
3110}
3111
7c5f152a 3112static char *lookup_uid(uid_t uid) {
ef2f1067 3113 long bufsize;
a05f97b3
LP
3114 char *name;
3115 _cleanup_free_ char *buf = NULL;
ef2f1067 3116 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
3117
3118 /* Shortcut things to avoid NSS lookups */
3119 if (uid == 0)
3120 return strdup("root");
3121
7c5f152a
LP
3122 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
3123 if (bufsize <= 0)
ef2f1067
LP
3124 bufsize = 4096;
3125
7c5f152a
LP
3126 buf = malloc(bufsize);
3127 if (!buf)
ef2f1067
LP
3128 return NULL;
3129
a05f97b3
LP
3130 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
3131 return strdup(pw->pw_name);
ef2f1067
LP
3132
3133 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
3134 return NULL;
3135
3136 return name;
3137}
3138
7c5f152a
LP
3139char* getlogname_malloc(void) {
3140 uid_t uid;
3141 struct stat st;
3142
3143 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
3144 uid = st.st_uid;
3145 else
3146 uid = getuid();
3147
3148 return lookup_uid(uid);
3149}
3150
3151char *getusername_malloc(void) {
3152 const char *e;
3153
3154 e = getenv("USER");
3155 if (e)
3156 return strdup(e);
3157
3158 return lookup_uid(getuid());
3159}
3160
fc116c6a
LP
3161int getttyname_malloc(int fd, char **r) {
3162 char path[PATH_MAX], *c;
618e02c7 3163 int k;
8c6db833
LP
3164
3165 assert(r);
ef2f1067 3166
a05f97b3
LP
3167 k = ttyname_r(fd, path, sizeof(path));
3168 if (k != 0)
618e02c7 3169 return -k;
ef2f1067
LP
3170
3171 char_array_0(path);
3172
a05f97b3
LP
3173 c = strdup(startswith(path, "/dev/") ? path + 5 : path);
3174 if (!c)
8c6db833
LP
3175 return -ENOMEM;
3176
3177 *r = c;
3178 return 0;
3179}
3180
fc116c6a
LP
3181int getttyname_harder(int fd, char **r) {
3182 int k;
3183 char *s;
3184
a05f97b3
LP
3185 k = getttyname_malloc(fd, &s);
3186 if (k < 0)
fc116c6a
LP
3187 return k;
3188
3189 if (streq(s, "tty")) {
3190 free(s);
4d6d6518 3191 return get_ctty(0, NULL, r);
fc116c6a
LP
3192 }
3193
3194 *r = s;
3195 return 0;
3196}
3197
4d6d6518 3198int get_ctty_devnr(pid_t pid, dev_t *d) {
fc116c6a 3199 int k;
4d6d6518 3200 char line[LINE_MAX], *p, *fn;
fc116c6a
LP
3201 unsigned long ttynr;
3202 FILE *f;
3203
4d6d6518
LP
3204 if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
3205 return -ENOMEM;
3206
3207 f = fopen(fn, "re");
3208 free(fn);
3209 if (!f)
fc116c6a
LP
3210 return -errno;
3211
4d6d6518 3212 if (!fgets(line, sizeof(line), f)) {
35d50f55 3213 k = feof(f) ? -EIO : -errno;
fc116c6a
LP
3214 fclose(f);
3215 return k;
3216 }
3217
3218 fclose(f);
3219
4d6d6518
LP
3220 p = strrchr(line, ')');
3221 if (!p)
fc116c6a
LP
3222 return -EIO;
3223
3224 p++;
3225
3226 if (sscanf(p, " "
3227 "%*c " /* state */
3228 "%*d " /* ppid */
3229 "%*d " /* pgrp */
3230 "%*d " /* session */
3231 "%lu ", /* ttynr */
3232 &ttynr) != 1)
3233 return -EIO;
3234
3235 *d = (dev_t) ttynr;
3236 return 0;
3237}
3238
4d6d6518 3239int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
fc116c6a 3240 int k;
20c03b7b 3241 char fn[PATH_MAX], *s, *b, *p;
fc116c6a
LP
3242 dev_t devnr;
3243
3244 assert(r);
3245
4d6d6518
LP
3246 k = get_ctty_devnr(pid, &devnr);
3247 if (k < 0)
fc116c6a
LP
3248 return k;
3249
3250 snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
3251 char_array_0(fn);
3252
3253 if ((k = readlink_malloc(fn, &s)) < 0) {
3254
3255 if (k != -ENOENT)
3256 return k;
3257
46824d0e
LP
3258 /* This is an ugly hack */
3259 if (major(devnr) == 136) {
3260 if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
3261 return -ENOMEM;
3262
3263 *r = b;
3264 if (_devnr)
3265 *_devnr = devnr;
3266
3267 return 0;
3268 }
3269
fc116c6a
LP
3270 /* Probably something like the ptys which have no
3271 * symlink in /dev/char. Let's return something
3272 * vaguely useful. */
3273
3274 if (!(b = strdup(fn + 5)))
3275 return -ENOMEM;
3276
3277 *r = b;
46824d0e
LP
3278 if (_devnr)
3279 *_devnr = devnr;
3280
fc116c6a
LP
3281 return 0;
3282 }
3283
3284 if (startswith(s, "/dev/"))
3285 p = s + 5;
3286 else if (startswith(s, "../"))
3287 p = s + 3;
3288 else
3289 p = s;
3290
3291 b = strdup(p);
3292 free(s);
3293
3294 if (!b)
3295 return -ENOMEM;
3296
3297 *r = b;
46824d0e
LP
3298 if (_devnr)
3299 *_devnr = devnr;
3300
fc116c6a
LP
3301 return 0;
3302}
3303
f56d5db9 3304int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
8c6db833
LP
3305 DIR *d;
3306 int ret = 0;
3307
3308 assert(fd >= 0);
3309
3310 /* This returns the first error we run into, but nevertheless
7925c22a 3311 * tries to go on. This closes the passed fd. */
8c6db833 3312
d4d046e3
LP
3313 d = fdopendir(fd);
3314 if (!d) {
8c6db833 3315 close_nointr_nofail(fd);
4c633005
LP
3316
3317 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
3318 }
3319
3320 for (;;) {
7d5e9c0f
LP
3321 struct dirent *de;
3322 union dirent_storage buf;
7925c22a
LP
3323 bool is_dir, keep_around;
3324 struct stat st;
8c6db833
LP
3325 int r;
3326
7d5e9c0f 3327 r = readdir_r(d, &buf.de, &de);
d4d046e3
LP
3328 if (r != 0 && ret == 0) {
3329 ret = -r;
8c6db833
LP
3330 break;
3331 }
3332
3333 if (!de)
3334 break;
3335
3336 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
3337 continue;
3338
7925c22a
LP
3339 if (de->d_type == DT_UNKNOWN ||
3340 honour_sticky ||
3341 (de->d_type == DT_DIR && root_dev)) {
8c6db833 3342 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 3343 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3344 ret = -errno;
3345 continue;
3346 }
3347
3348 is_dir = S_ISDIR(st.st_mode);
7925c22a
LP
3349 keep_around =
3350 honour_sticky &&
3351 (st.st_uid == 0 || st.st_uid == getuid()) &&
3352 (st.st_mode & S_ISVTX);
ad293f5a 3353 } else {
8c6db833 3354 is_dir = de->d_type == DT_DIR;
7925c22a 3355 keep_around = false;
ad293f5a 3356 }
8c6db833
LP
3357
3358 if (is_dir) {
3359 int subdir_fd;
8c6db833 3360
597f43c7 3361 /* if root_dev is set, remove subdirectories only, if device is same as dir */
7925c22a
LP
3362 if (root_dev && st.st_dev != root_dev->st_dev)
3363 continue;
8c6db833 3364
7925c22a
LP
3365 subdir_fd = openat(fd, de->d_name,
3366 O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3367 if (subdir_fd < 0) {
3368 if (ret == 0 && errno != ENOENT)
3369 ret = -errno;
3370 continue;
3371 }
3372
b3d28469 3373 r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
7925c22a
LP
3374 if (r < 0 && ret == 0)
3375 ret = r;
3376
3377 if (!keep_around)
3378 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
ad293f5a
LP
3379 if (ret == 0 && errno != ENOENT)
3380 ret = -errno;
3381 }
3382
3383 } else if (!only_dirs && !keep_around) {
8c6db833
LP
3384
3385 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 3386 if (ret == 0 && errno != ENOENT)
8c6db833
LP
3387 ret = -errno;
3388 }
3389 }
3390 }
3391
3392 closedir(d);
3393
3394 return ret;
3395}
3396
f56d5db9
LP
3397int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
3398 struct statfs s;
3399
3400 assert(fd >= 0);
3401
3402 if (fstatfs(fd, &s) < 0) {
3403 close_nointr_nofail(fd);
3404 return -errno;
3405 }
3406
3407 /* We refuse to clean disk file systems with this call. This
3408 * is extra paranoia just to be sure we never ever remove
3409 * non-state data */
3410
3411 if (s.f_type != TMPFS_MAGIC &&
3412 s.f_type != RAMFS_MAGIC) {
3413 log_error("Attempted to remove disk file system, and we can't allow that.");
3414 close_nointr_nofail(fd);
3415 return -EPERM;
3416 }
3417
3418 return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
3419}
3420
3421static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
3422 int fd, r;
3423 struct statfs s;
8c6db833
LP
3424
3425 assert(path);
3426
f56d5db9
LP
3427 /* We refuse to clean the root file system with this
3428 * call. This is extra paranoia to never cause a really
3429 * seriously broken system. */
3430 if (path_equal(path, "/")) {
3431 log_error("Attempted to remove entire root file system, and we can't allow that.");
3432 return -EPERM;
3433 }
461b1822 3434
d4d046e3
LP
3435 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
3436 if (fd < 0) {
8c6db833
LP
3437
3438 if (errno != ENOTDIR)
3439 return -errno;
3440
f56d5db9
LP
3441 if (!dangerous) {
3442 if (statfs(path, &s) < 0)
3443 return -errno;
3444
3445 if (s.f_type != TMPFS_MAGIC &&
3446 s.f_type != RAMFS_MAGIC) {
3447 log_error("Attempted to remove disk file system, and we can't allow that.");
3448 return -EPERM;
3449 }
3450 }
3451
8c6db833 3452 if (delete_root && !only_dirs)
d4d046e3 3453 if (unlink(path) < 0 && errno != ENOENT)
8c6db833
LP
3454 return -errno;
3455
3456 return 0;
3457 }
3458
f56d5db9
LP
3459 if (!dangerous) {
3460 if (fstatfs(fd, &s) < 0) {
3461 close_nointr_nofail(fd);
3462 return -errno;
3463 }
ad293f5a 3464
f56d5db9
LP
3465 if (s.f_type != TMPFS_MAGIC &&
3466 s.f_type != RAMFS_MAGIC) {
3467 log_error("Attempted to remove disk file system, and we can't allow that.");
3468 close_nointr_nofail(fd);
3469 return -EPERM;
3470 }
3471 }
3472
3473 r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
ad293f5a
LP
3474 if (delete_root) {
3475
8d53b453 3476 if (honour_sticky && file_is_priv_sticky(path) > 0)
ad293f5a 3477 return r;
8c6db833 3478
e27796a0 3479 if (rmdir(path) < 0 && errno != ENOENT) {
8c6db833
LP
3480 if (r == 0)
3481 r = -errno;
3482 }
ad293f5a 3483 }
8c6db833
LP
3484
3485 return r;
3486}
3487
f56d5db9
LP
3488int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3489 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
3490}
3491
3492int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
3493 return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
3494}
3495
8c6db833
LP
3496int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
3497 assert(path);
3498
3499 /* Under the assumption that we are running privileged we
3500 * first change the access mode and only then hand out
3501 * ownership to avoid a window where access is too open. */
3502
8d53b453
LP
3503 if (mode != (mode_t) -1)
3504 if (chmod(path, mode) < 0)
3505 return -errno;
8c6db833 3506
8d53b453
LP
3507 if (uid != (uid_t) -1 || gid != (gid_t) -1)
3508 if (chown(path, uid, gid) < 0)
3509 return -errno;
8c6db833
LP
3510
3511 return 0;
ef2f1067
LP
3512}
3513
f4b47811
LP
3514int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
3515 assert(fd >= 0);
3516
3517 /* Under the assumption that we are running privileged we
3518 * first change the access mode and only then hand out
3519 * ownership to avoid a window where access is too open. */
3520
3521 if (fchmod(fd, mode) < 0)
3522 return -errno;
3523
3524 if (fchown(fd, uid, gid) < 0)
3525 return -errno;
3526
3527 return 0;
3528}
3529
82c121a4
LP
3530cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
3531 cpu_set_t *r;
3532 unsigned n = 1024;
3533
3534 /* Allocates the cpuset in the right size */
3535
3536 for (;;) {
3537 if (!(r = CPU_ALLOC(n)))
3538 return NULL;
3539
3540 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
3541 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
3542
3543 if (ncpus)
3544 *ncpus = n;
3545
3546 return r;
3547 }
3548
3549 CPU_FREE(r);
3550
3551 if (errno != EINVAL)
3552 return NULL;
3553
3554 n *= 2;
3555 }
3556}
3557
669bec5d 3558int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
9ab7a8d2 3559 static const char status_indent[] = " "; /* "[" STATUS "] " */
669bec5d
LP
3560 _cleanup_free_ char *s = NULL;
3561 _cleanup_close_ int fd = -1;
81beb750
LP
3562 struct iovec iovec[5];
3563 int n = 0;
9e58ff9c
LP
3564
3565 assert(format);
3566
9ab7a8d2 3567 /* This is independent of logging, as status messages are
9e58ff9c
LP
3568 * optional and go exclusively to the console. */
3569
3570 if (vasprintf(&s, format, ap) < 0)
669bec5d 3571 return log_oom();
9e58ff9c 3572
67e5cc4f 3573 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
81beb750 3574 if (fd < 0)
669bec5d 3575 return fd;
9e58ff9c 3576
67e5cc4f 3577 if (ellipse) {
9ab7a8d2
MS
3578 char *e;
3579 size_t emax, sl;
3580 int c;
3581
67e5cc4f
LP
3582 c = fd_columns(fd);
3583 if (c <= 0)
3584 c = 80;
81beb750 3585
669bec5d 3586 sl = status ? sizeof(status_indent)-1 : 0;
9ab7a8d2
MS
3587
3588 emax = c - sl - 1;
3589 if (emax < 3)
3590 emax = 3;
81beb750 3591
67e5cc4f
LP
3592 e = ellipsize(s, emax, 75);
3593 if (e) {
3594 free(s);
3595 s = e;
3596 }
81beb750
LP
3597 }
3598
3599 zero(iovec);
81beb750 3600
9ab7a8d2
MS
3601 if (status) {
3602 if (!isempty(status)) {
3603 IOVEC_SET_STRING(iovec[n++], "[");
3604 IOVEC_SET_STRING(iovec[n++], status);
3605 IOVEC_SET_STRING(iovec[n++], "] ");
3606 } else
3607 IOVEC_SET_STRING(iovec[n++], status_indent);
81beb750
LP
3608 }
3609
9ab7a8d2
MS
3610 IOVEC_SET_STRING(iovec[n++], s);
3611 IOVEC_SET_STRING(iovec[n++], "\n");
81beb750 3612
669bec5d
LP
3613 if (writev(fd, iovec, n) < 0)
3614 return -errno;
9e58ff9c 3615
669bec5d 3616 return 0;
9e58ff9c
LP
3617}
3618
669bec5d 3619int status_printf(const char *status, bool ellipse, const char *format, ...) {
c846ff47 3620 va_list ap;
669bec5d 3621 int r;
c846ff47
LP
3622
3623 assert(format);
3624
3625 va_start(ap, format);
669bec5d 3626 r = status_vprintf(status, ellipse, format, ap);
c846ff47 3627 va_end(ap);
669bec5d
LP
3628
3629 return r;
c846ff47
LP
3630}
3631
669bec5d 3632int status_welcome(void) {
10aa7034 3633 int r;
669bec5d
LP
3634 _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
3635
3636 r = parse_env_file("/etc/os-release", NEWLINE,
3637 "PRETTY_NAME", &pretty_name,
3638 "ANSI_COLOR", &ansi_color,
3639 NULL);
3640 if (r < 0 && r != -ENOENT)
3641 log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3642
3643 return status_printf(NULL, false,
3644 "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3645 isempty(ansi_color) ? "1" : ansi_color,
3646 isempty(pretty_name) ? "Linux" : pretty_name);
c846ff47
LP
3647}
3648
fab56fc5
LP
3649char *replace_env(const char *format, char **env) {
3650 enum {
3651 WORD,
c24eb49e 3652 CURLY,
fab56fc5
LP
3653 VARIABLE
3654 } state = WORD;
3655
3656 const char *e, *word = format;
3657 char *r = NULL, *k;
3658
3659 assert(format);
3660
3661 for (e = format; *e; e ++) {
3662
3663 switch (state) {
3664
3665 case WORD:
3666 if (*e == '$')
c24eb49e 3667 state = CURLY;
fab56fc5
LP
3668 break;
3669
c24eb49e
LP
3670 case CURLY:
3671 if (*e == '{') {
fab56fc5
LP
3672 if (!(k = strnappend(r, word, e-word-1)))
3673 goto fail;
3674
3675 free(r);
3676 r = k;
3677
3678 word = e-1;
3679 state = VARIABLE;
3680
3681 } else if (*e == '$') {
3682 if (!(k = strnappend(r, word, e-word)))
3683 goto fail;
3684
3685 free(r);
3686 r = k;
3687
3688 word = e+1;
3689 state = WORD;
3690 } else
3691 state = WORD;
3692 break;
3693
3694 case VARIABLE:
c24eb49e 3695 if (*e == '}') {
b95cf362 3696 const char *t;
fab56fc5 3697
b95cf362
LP
3698 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
3699 t = "";
fab56fc5 3700
b95cf362
LP
3701 if (!(k = strappend(r, t)))
3702 goto fail;
fab56fc5 3703
b95cf362
LP
3704 free(r);
3705 r = k;
fab56fc5 3706
b95cf362 3707 word = e+1;
fab56fc5
LP
3708 state = WORD;
3709 }
3710 break;
3711 }
3712 }
3713
3714 if (!(k = strnappend(r, word, e-word)))
3715 goto fail;
3716
3717 free(r);
3718 return k;
3719
3720fail:
3721 free(r);
3722 return NULL;
3723}
3724
3725char **replace_env_argv(char **argv, char **env) {
3726 char **r, **i;
c24eb49e
LP
3727 unsigned k = 0, l = 0;
3728
3729 l = strv_length(argv);
fab56fc5 3730
c24eb49e 3731 if (!(r = new(char*, l+1)))
fab56fc5
LP
3732 return NULL;
3733
3734 STRV_FOREACH(i, argv) {
c24eb49e
LP
3735
3736 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
3737 if ((*i)[0] == '$' && (*i)[1] != '{') {
3738 char *e;
3739 char **w, **m;
3740 unsigned q;
c24eb49e 3741
b95cf362 3742 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
3743
3744 if (!(m = strv_split_quoted(e))) {
3745 r[k] = NULL;
3746 strv_free(r);
3747 return NULL;
3748 }
b95cf362
LP
3749 } else
3750 m = NULL;
c24eb49e 3751
b95cf362
LP
3752 q = strv_length(m);
3753 l = l + q - 1;
c24eb49e 3754
b95cf362
LP
3755 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
3756 r[k] = NULL;
3757 strv_free(r);
3758 strv_free(m);
3759 return NULL;
3760 }
c24eb49e 3761
b95cf362
LP
3762 r = w;
3763 if (m) {
c24eb49e
LP
3764 memcpy(r + k, m, q * sizeof(char*));
3765 free(m);
c24eb49e 3766 }
b95cf362
LP
3767
3768 k += q;
3769 continue;
c24eb49e
LP
3770 }
3771
3772 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
3773 if (!(r[k++] = replace_env(*i, env))) {
3774 strv_free(r);
3775 return NULL;
3776 }
3777 }
3778
3779 r[k] = NULL;
3780 return r;
3781}
3782
81beb750
LP
3783int fd_columns(int fd) {
3784 struct winsize ws;
3785 zero(ws);
3786
3787 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3788 return -errno;
3789
3790 if (ws.ws_col <= 0)
3791 return -EIO;
3792
3793 return ws.ws_col;
3794}
3795
11f96fac 3796static unsigned columns_cached(bool cached) {
585314e8 3797 static __thread int env_columns = -1;
fa776d8e
LP
3798 const char *e;
3799
11f96fac 3800 if (_likely_(parsed_columns > 0 && cached))
fa776d8e
LP
3801 return parsed_columns;
3802
11f96fac
ZJS
3803 if (_unlikely_(env_columns == -1)) {
3804 e = getenv("COLUMNS");
3805 if (e)
3806 env_columns = atoi(e);
3807 else
3808 env_columns = 0;
3809 }
fa776d8e 3810
11f96fac
ZJS
3811 if (env_columns > 0) {
3812 parsed_columns = env_columns;
3813 return parsed_columns;
3814 }
3815
3816 if (parsed_columns <= 0 || !cached)
81beb750 3817 parsed_columns = fd_columns(STDOUT_FILENO);
fa776d8e
LP
3818
3819 if (parsed_columns <= 0)
3820 parsed_columns = 80;
3821
3822 return parsed_columns;
3823}
3824
11f96fac
ZJS
3825unsigned columns(void) {
3826 return columns_cached(true);
3827}
3828
3829unsigned columns_uncached(void) {
3830 return columns_cached(false);
3831}
3832
585314e8
DR
3833/* intended to be used as a SIGWINCH sighandler */
3834void columns_cache_reset(int signum) {
3835 parsed_columns = 0;
3836}
3837
8f2d43a0
LP
3838int fd_lines(int fd) {
3839 struct winsize ws;
3840 zero(ws);
3841
3842 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3843 return -errno;
3844
3845 if (ws.ws_row <= 0)
3846 return -EIO;
3847
3848 return ws.ws_row;
3849}
3850
3851unsigned lines(void) {
3852 static __thread int parsed_lines = 0;
3853 const char *e;
3854
3855 if (_likely_(parsed_lines > 0))
3856 return parsed_lines;
3857
3858 e = getenv("LINES");
3859 if (e)
3860 parsed_lines = atoi(e);
3861
3862 if (parsed_lines <= 0)
3863 parsed_lines = fd_lines(STDOUT_FILENO);
3864
3865 if (parsed_lines <= 0)
3866 parsed_lines = 25;
3867
3868 return parsed_lines;
3869}
3870
b4f10a5e
LP
3871int running_in_chroot(void) {
3872 struct stat a, b;
3873
3874 zero(a);
3875 zero(b);
3876
3877 /* Only works as root */
3878
3879 if (stat("/proc/1/root", &a) < 0)
3880 return -errno;
3881
3882 if (stat("/", &b) < 0)
3883 return -errno;
3884
3885 return
3886 a.st_dev != b.st_dev ||
3887 a.st_ino != b.st_ino;
3888}
3889
72f59706
LP
3890char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3891 size_t x;
8fe914ec
LP
3892 char *r;
3893
3894 assert(s);
3895 assert(percent <= 100);
72f59706 3896 assert(new_length >= 3);
8fe914ec 3897
72f59706
LP
3898 if (old_length <= 3 || old_length <= new_length)
3899 return strndup(s, old_length);
8fe914ec 3900
72f59706
LP
3901 r = new0(char, new_length+1);
3902 if (!r)
8fe914ec
LP
3903 return r;
3904
72f59706 3905 x = (new_length * percent) / 100;
8fe914ec 3906
72f59706
LP
3907 if (x > new_length - 3)
3908 x = new_length - 3;
8fe914ec
LP
3909
3910 memcpy(r, s, x);
3911 r[x] = '.';
3912 r[x+1] = '.';
3913 r[x+2] = '.';
3914 memcpy(r + x + 3,
72f59706
LP
3915 s + old_length - (new_length - x - 3),
3916 new_length - x - 3);
8fe914ec
LP
3917
3918 return r;
3919}
3920
72f59706
LP
3921char *ellipsize(const char *s, size_t length, unsigned percent) {
3922 return ellipsize_mem(s, strlen(s), length, percent);
3923}
3924
f6144808
LP
3925int touch(const char *path) {
3926 int fd;
3927
3928 assert(path);
3929
73836c5c
LP
3930 /* This just opens the file for writing, ensuring it
3931 * exists. It doesn't call utimensat() the way /usr/bin/touch
3932 * does it. */
3933
3934 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
3935 if (fd < 0)
f6144808
LP
3936 return -errno;
3937
3938 close_nointr_nofail(fd);
3939 return 0;
3940}
afea26ad 3941
97c4a07d 3942char *unquote(const char *s, const char* quotes) {
11ce3427
LP
3943 size_t l;
3944 assert(s);
3945
73836c5c
LP
3946 /* This is rather stupid, simply removes the heading and
3947 * trailing quotes if there is one. Doesn't care about
57f30678
LP
3948 * escaping or anything. We should make this smarter one
3949 * day...*/
73836c5c 3950
31ed59c5
LP
3951 l = strlen(s);
3952 if (l < 2)
11ce3427
LP
3953 return strdup(s);
3954
97c4a07d 3955 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
3956 return strndup(s+1, l-2);
3957
3958 return strdup(s);
3959}
3960
5f7c426e 3961char *normalize_env_assignment(const char *s) {
57f30678
LP
3962 _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
3963 char *eq, *r;
5f7c426e 3964
57f30678
LP
3965 eq = strchr(s, '=');
3966 if (!eq) {
3967 char *t;
5f7c426e 3968
57f30678
LP
3969 r = strdup(s);
3970 if (!r)
5f7c426e
LP
3971 return NULL;
3972
57f30678
LP
3973 t = strstrip(r);
3974 if (t == r)
3975 return r;
3976
3977 memmove(r, t, strlen(t) + 1);
3978 return r;
5f7c426e
LP
3979 }
3980
57f30678
LP
3981 name = strndup(s, eq - s);
3982 if (!name)
5f7c426e
LP
3983 return NULL;
3984
57f30678
LP
3985 p = strdup(eq + 1);
3986 if (!p)
5f7c426e 3987 return NULL;
5f7c426e
LP
3988
3989 value = unquote(strstrip(p), QUOTES);
57f30678 3990 if (!value)
5f7c426e 3991 return NULL;
5f7c426e 3992
57f30678 3993 if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
5f7c426e
LP
3994 r = NULL;
3995
5f7c426e
LP
3996 return r;
3997}
3998
8e12a6ae 3999int wait_for_terminate(pid_t pid, siginfo_t *status) {
1968a360
LP
4000 siginfo_t dummy;
4001
2e78aa99 4002 assert(pid >= 1);
1968a360
LP
4003
4004 if (!status)
4005 status = &dummy;
2e78aa99
LP
4006
4007 for (;;) {
8e12a6ae
LP
4008 zero(*status);
4009
4010 if (waitid(P_PID, pid, status, WEXITED) < 0) {
2e78aa99
LP
4011
4012 if (errno == EINTR)
4013 continue;
4014
4015 return -errno;
4016 }
4017
4018 return 0;
4019 }
4020}
4021
97c4a07d
LP
4022int wait_for_terminate_and_warn(const char *name, pid_t pid) {
4023 int r;
4024 siginfo_t status;
4025
4026 assert(name);
4027 assert(pid > 1);
4028
d87be9b0
LP
4029 r = wait_for_terminate(pid, &status);
4030 if (r < 0) {
97c4a07d
LP
4031 log_warning("Failed to wait for %s: %s", name, strerror(-r));
4032 return r;
4033 }
4034
4035 if (status.si_code == CLD_EXITED) {
4036 if (status.si_status != 0) {
4037 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 4038 return status.si_status;
97c4a07d
LP
4039 }
4040
4041 log_debug("%s succeeded.", name);
4042 return 0;
4043
4044 } else if (status.si_code == CLD_KILLED ||
4045 status.si_code == CLD_DUMPED) {
4046
4047 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
4048 return -EPROTO;
4049 }
4050
4051 log_warning("%s failed due to unknown reason.", name);
4052 return -EPROTO;
97c4a07d
LP
4053}
4054
6a39419f 4055_noreturn_ void freeze(void) {
720ce21d
LP
4056
4057 /* Make sure nobody waits for us on a socket anymore */
4058 close_all_fds(NULL, 0);
4059
c29597a1
LP
4060 sync();
4061
3c14d26c
LP
4062 for (;;)
4063 pause();
4064}
4065
00dc5d76
LP
4066bool null_or_empty(struct stat *st) {
4067 assert(st);
4068
4069 if (S_ISREG(st->st_mode) && st->st_size <= 0)
4070 return true;
4071
c8f26f42 4072 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
4073 return true;
4074
4075 return false;
4076}
4077
83096483
LP
4078int null_or_empty_path(const char *fn) {
4079 struct stat st;
4080
4081 assert(fn);
4082
4083 if (stat(fn, &st) < 0)
4084 return -errno;
4085
4086 return null_or_empty(&st);
4087}
4088
a247755d 4089DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
4090 int nfd;
4091 DIR *d;
4092
73836c5c
LP
4093 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
4094 if (nfd < 0)
c4731d11
LP
4095 return NULL;
4096
73836c5c
LP
4097 d = fdopendir(nfd);
4098 if (!d) {
c4731d11
LP
4099 close_nointr_nofail(nfd);
4100 return NULL;
4101 }
4102
4103 return d;
3b63d2d3
LP
4104}
4105
8a0867d6
LP
4106int signal_from_string_try_harder(const char *s) {
4107 int signo;
4108 assert(s);
4109
73836c5c
LP
4110 signo = signal_from_string(s);
4111 if (signo <= 0)
8a0867d6
LP
4112 if (startswith(s, "SIG"))
4113 return signal_from_string(s+3);
4114
4115 return signo;
4116}
4117
10717a1a
LP
4118void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
4119
4120 assert(f);
4121 assert(name);
4122 assert(t);
4123
4124 if (!dual_timestamp_is_set(t))
4125 return;
4126
4127 fprintf(f, "%s=%llu %llu\n",
4128 name,
4129 (unsigned long long) t->realtime,
4130 (unsigned long long) t->monotonic);
4131}
4132
799fd0fd 4133void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
10717a1a
LP
4134 unsigned long long a, b;
4135
10717a1a
LP
4136 assert(value);
4137 assert(t);
4138
4139 if (sscanf(value, "%lli %llu", &a, &b) != 2)
4140 log_debug("Failed to parse finish timestamp value %s", value);
4141 else {
4142 t->realtime = a;
4143 t->monotonic = b;
4144 }
4145}
4146
383182b5 4147static char *tag_to_udev_node(const char *tagvalue, const char *by) {
e23a0ce8
LP
4148 char *dn, *t, *u;
4149 int r;
4150
4151 /* FIXME: to follow udev's logic 100% we need to leave valid
4152 * UTF8 chars unescaped */
4153
383182b5
DR
4154 u = unquote(tagvalue, "\"\'");
4155 if (u == NULL)
4156 return NULL;
e23a0ce8 4157
383182b5
DR
4158 t = xescape(u, "/ ");
4159 free(u);
e23a0ce8 4160
383182b5
DR
4161 if (t == NULL)
4162 return NULL;
e23a0ce8 4163
383182b5
DR
4164 r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
4165 free(t);
e23a0ce8 4166
383182b5
DR
4167 if (r < 0)
4168 return NULL;
e23a0ce8 4169
383182b5
DR
4170 return dn;
4171}
e23a0ce8 4172
383182b5 4173char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
4174 assert(p);
4175
383182b5
DR
4176 if (startswith(p, "LABEL="))
4177 return tag_to_udev_node(p+6, "label");
e23a0ce8 4178
383182b5
DR
4179 if (startswith(p, "UUID="))
4180 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 4181
84cc2abf
DR
4182 if (startswith(p, "PARTUUID="))
4183 return tag_to_udev_node(p+9, "partuuid");
4184
4185 if (startswith(p, "PARTLABEL="))
4186 return tag_to_udev_node(p+10, "partlabel");
4187
e23a0ce8
LP
4188 return strdup(p);
4189}
4190
f212ac12
LP
4191bool tty_is_vc(const char *tty) {
4192 assert(tty);
4193
4194 if (startswith(tty, "/dev/"))
4195 tty += 5;
4196
98a28fef
LP
4197 return vtnr_from_tty(tty) >= 0;
4198}
4199
d1122ad5
LP
4200bool tty_is_console(const char *tty) {
4201 assert(tty);
4202
4203 if (startswith(tty, "/dev/"))
4204 tty += 5;
4205
4206 return streq(tty, "console");
4207}
4208
98a28fef
LP
4209int vtnr_from_tty(const char *tty) {
4210 int i, r;
4211
4212 assert(tty);
4213
4214 if (startswith(tty, "/dev/"))
4215 tty += 5;
4216
4217 if (!startswith(tty, "tty") )
4218 return -EINVAL;
4219
4220 if (tty[3] < '0' || tty[3] > '9')
4221 return -EINVAL;
4222
4223 r = safe_atoi(tty+3, &i);
4224 if (r < 0)
4225 return r;
4226
4227 if (i < 0 || i > 63)
4228 return -EINVAL;
4229
4230 return i;
f212ac12
LP
4231}
4232
3043935f 4233bool tty_is_vc_resolve(const char *tty) {
3030ccd7 4234 char *active = NULL;
3043935f 4235 bool b;
3030ccd7 4236
e3aa71c3
LP
4237 assert(tty);
4238
4239 if (startswith(tty, "/dev/"))
4240 tty += 5;
4241
3d9a4122
LP
4242 /* Resolve where /dev/console is pointing to, if /sys is
4243 * actually ours (i.e. not read-only-mounted which is a sign
4244 * for container setups) */
4245 if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
3030ccd7 4246 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4247 /* If multiple log outputs are configured the
4248 * last one is what /dev/console points to */
3043935f
LP
4249 tty = strrchr(active, ' ');
4250 if (tty)
079a09fb
LP
4251 tty++;
4252 else
4253 tty = active;
3030ccd7
LP
4254 }
4255
3043935f 4256 b = tty_is_vc(tty);
3030ccd7 4257 free(active);
e3aa71c3 4258
3043935f
LP
4259 return b;
4260}
4261
4262const char *default_term_for_tty(const char *tty) {
4263 assert(tty);
4264
acda6a05 4265 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
4266}
4267
87d2c1ff 4268bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4269 assert(de);
4270
4271 if (ignore_file(de->d_name))
4272 return false;
4273
4274 if (de->d_type != DT_REG &&
4275 de->d_type != DT_LNK &&
4276 de->d_type != DT_UNKNOWN)
4277 return false;
4278
4279 return true;
4280}
4281
87d2c1ff
LP
4282bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4283 assert(de);
4284
a228a22f
LP
4285 if (de->d_type != DT_REG &&
4286 de->d_type != DT_LNK &&
4287 de->d_type != DT_UNKNOWN)
4288 return false;
4289
4290 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
4291 return false;
4292
4293 return endswith(de->d_name, suffix);
4294}
4295
83cc030f
LP
4296void execute_directory(const char *directory, DIR *d, char *argv[]) {
4297 DIR *_d = NULL;
4298 struct dirent *de;
4299 Hashmap *pids = NULL;
4300
4301 assert(directory);
4302
4303 /* Executes all binaries in a directory in parallel and waits
4304 * until all they all finished. */
4305
4306 if (!d) {
4307 if (!(_d = opendir(directory))) {
4308
4309 if (errno == ENOENT)
4310 return;
4311
4312 log_error("Failed to enumerate directory %s: %m", directory);
4313 return;
4314 }
4315
4316 d = _d;
4317 }
4318
4319 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4320 log_error("Failed to allocate set.");
4321 goto finish;
4322 }
4323
4324 while ((de = readdir(d))) {
4325 char *path;
4326 pid_t pid;
4327 int k;
4328
fb19a739 4329 if (!dirent_is_file(de))
83cc030f
LP
4330 continue;
4331
4332 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
0d0f0c50 4333 log_oom();
83cc030f
LP
4334 continue;
4335 }
4336
4337 if ((pid = fork()) < 0) {
4338 log_error("Failed to fork: %m");
4339 free(path);
4340 continue;
4341 }
4342
4343 if (pid == 0) {
4344 char *_argv[2];
4345 /* Child */
4346
4347 if (!argv) {
4348 _argv[0] = path;
4349 _argv[1] = NULL;
4350 argv = _argv;
4351 } else
6edd7d0a 4352 argv[0] = path;
83cc030f
LP
4353
4354 execv(path, argv);
4355
4356 log_error("Failed to execute %s: %m", path);
4357 _exit(EXIT_FAILURE);
4358 }
4359
4360 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4361
4362 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4363 log_error("Failed to add PID to set: %s", strerror(-k));
4364 free(path);
4365 }
4366 }
4367
4368 while (!hashmap_isempty(pids)) {
ec3f9b53 4369 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
4370 siginfo_t si;
4371 char *path;
4372
4373 zero(si);
ec3f9b53 4374 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
4375
4376 if (errno == EINTR)
4377 continue;
4378
4379 log_error("waitid() failed: %m");
4380 goto finish;
4381 }
4382
4383 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
96342de6 4384 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
83cc030f
LP
4385 if (si.si_code == CLD_EXITED)
4386 log_error("%s exited with exit status %i.", path, si.si_status);
4387 else
4388 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4389 } else
4390 log_debug("%s exited successfully.", path);
4391
4392 free(path);
4393 }
4394 }
4395
4396finish:
4397 if (_d)
4398 closedir(_d);
4399
4400 if (pids)
4401 hashmap_free_free(pids);
4402}
4403
430c18ed
LP
4404int kill_and_sigcont(pid_t pid, int sig) {
4405 int r;
4406
4407 r = kill(pid, sig) < 0 ? -errno : 0;
4408
4409 if (r >= 0)
4410 kill(pid, SIGCONT);
4411
4412 return r;
4413}
4414
05feefe0
LP
4415bool nulstr_contains(const char*nulstr, const char *needle) {
4416 const char *i;
4417
4418 if (!nulstr)
4419 return false;
4420
4421 NULSTR_FOREACH(i, nulstr)
4422 if (streq(i, needle))
4423 return true;
4424
4425 return false;
4426}
4427
6faa1114 4428bool plymouth_running(void) {
9408a2d2 4429 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4430}
4431
9beb3f4d
LP
4432char* strshorten(char *s, size_t l) {
4433 assert(s);
4434
4435 if (l < strlen(s))
4436 s[l] = 0;
4437
4438 return s;
4439}
4440
4441static bool hostname_valid_char(char c) {
4442 return
4443 (c >= 'a' && c <= 'z') ||
4444 (c >= 'A' && c <= 'Z') ||
4445 (c >= '0' && c <= '9') ||
4446 c == '-' ||
4447 c == '_' ||
4448 c == '.';
4449}
4450
4451bool hostname_is_valid(const char *s) {
4452 const char *p;
4453
4454 if (isempty(s))
4455 return false;
4456
4457 for (p = s; *p; p++)
4458 if (!hostname_valid_char(*p))
4459 return false;
4460
4461 if (p-s > HOST_NAME_MAX)
4462 return false;
4463
4464 return true;
4465}
4466
4467char* hostname_cleanup(char *s) {
4468 char *p, *d;
4469
4470 for (p = s, d = s; *p; p++)
4471 if ((*p >= 'a' && *p <= 'z') ||
4472 (*p >= 'A' && *p <= 'Z') ||
4473 (*p >= '0' && *p <= '9') ||
4474 *p == '-' ||
4475 *p == '_' ||
4476 *p == '.')
4477 *(d++) = *p;
4478
4479 *d = 0;
4480
4481 strshorten(s, HOST_NAME_MAX);
4482 return s;
4483}
4484
1325aa42
LP
4485int pipe_eof(int fd) {
4486 struct pollfd pollfd;
4487 int r;
4488
4489 zero(pollfd);
4490 pollfd.fd = fd;
4491 pollfd.events = POLLIN|POLLHUP;
4492
4493 r = poll(&pollfd, 1, 0);
4494 if (r < 0)
4495 return -errno;
4496
4497 if (r == 0)
4498 return 0;
4499
4500 return pollfd.revents & POLLHUP;
4501}
4502
8f2d43a0 4503int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
4504 struct pollfd pollfd;
4505 int r;
4506
4507 zero(pollfd);
4508 pollfd.fd = fd;
4509 pollfd.events = event;
4510
8f2d43a0 4511 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
4512 if (r < 0)
4513 return -errno;
4514
4515 if (r == 0)
4516 return 0;
4517
4518 return pollfd.revents;
4519}
4520
5a3ab509
LP
4521int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4522 FILE *f;
4523 char *t;
4524 const char *fn;
4525 size_t k;
4526 int fd;
4527
4528 assert(path);
4529 assert(_f);
4530 assert(_temp_path);
4531
4532 t = new(char, strlen(path) + 1 + 6 + 1);
4533 if (!t)
4534 return -ENOMEM;
4535
9eb977db 4536 fn = path_get_file_name(path);
5a3ab509
LP
4537 k = fn-path;
4538 memcpy(t, path, k);
4539 t[k] = '.';
4540 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4541
4542 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4543 if (fd < 0) {
4544 free(t);
4545 return -errno;
4546 }
4547
4548 f = fdopen(fd, "we");
4549 if (!f) {
4550 unlink(t);
4551 free(t);
4552 return -errno;
4553 }
4554
4555 *_f = f;
4556 *_temp_path = t;
4557
4558 return 0;
4559}
4560
6ea832a2 4561int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4562 assert(fd >= 0);
4563
6ea832a2
LP
4564 if (ioctl(fd, TIOCVHANGUP) < 0)
4565 return -errno;
4566
4567 return 0;
4568}
4569
4570int terminal_vhangup(const char *name) {
4571 int fd, r;
4572
4573 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4574 if (fd < 0)
4575 return fd;
4576
4577 r = terminal_vhangup_fd(fd);
4578 close_nointr_nofail(fd);
4579
4580 return r;
4581}
4582
4583int vt_disallocate(const char *name) {
4584 int fd, r;
4585 unsigned u;
6ea832a2
LP
4586
4587 /* Deallocate the VT if possible. If not possible
4588 * (i.e. because it is the active one), at least clear it
4589 * entirely (including the scrollback buffer) */
4590
b83bc4e9
LP
4591 if (!startswith(name, "/dev/"))
4592 return -EINVAL;
4593
4594 if (!tty_is_vc(name)) {
4595 /* So this is not a VT. I guess we cannot deallocate
4596 * it then. But let's at least clear the screen */
4597
4598 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4599 if (fd < 0)
4600 return fd;
4601
8585357a
LP
4602 loop_write(fd,
4603 "\033[r" /* clear scrolling region */
4604 "\033[H" /* move home */
4605 "\033[2J", /* clear screen */
4606 10, false);
b83bc4e9
LP
4607 close_nointr_nofail(fd);
4608
4609 return 0;
4610 }
6ea832a2
LP
4611
4612 if (!startswith(name, "/dev/tty"))
4613 return -EINVAL;
4614
4615 r = safe_atou(name+8, &u);
4616 if (r < 0)
4617 return r;
4618
4619 if (u <= 0)
b83bc4e9 4620 return -EINVAL;
6ea832a2 4621
b83bc4e9 4622 /* Try to deallocate */
6ea832a2
LP
4623 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4624 if (fd < 0)
4625 return fd;
4626
4627 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4628 close_nointr_nofail(fd);
6ea832a2 4629
b83bc4e9
LP
4630 if (r >= 0)
4631 return 0;
6ea832a2 4632
b83bc4e9 4633 if (errno != EBUSY)
6ea832a2 4634 return -errno;
6ea832a2 4635
b83bc4e9
LP
4636 /* Couldn't deallocate, so let's clear it fully with
4637 * scrollback */
4638 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4639 if (fd < 0)
b83bc4e9 4640 return fd;
6ea832a2 4641
8585357a
LP
4642 loop_write(fd,
4643 "\033[r" /* clear scrolling region */
4644 "\033[H" /* move home */
4645 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4646 10, false);
b83bc4e9 4647 close_nointr_nofail(fd);
6ea832a2 4648
b83bc4e9 4649 return 0;
6ea832a2
LP
4650}
4651
34ca941c
LP
4652int copy_file(const char *from, const char *to) {
4653 int r, fdf, fdt;
4654
4655 assert(from);
4656 assert(to);
4657
4658 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4659 if (fdf < 0)
4660 return -errno;
4661
4662 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
4663 if (fdt < 0) {
4664 close_nointr_nofail(fdf);
4665 return -errno;
4666 }
4667
4668 for (;;) {
4669 char buf[PIPE_BUF];
4670 ssize_t n, k;
4671
4672 n = read(fdf, buf, sizeof(buf));
4673 if (n < 0) {
4674 r = -errno;
4675
4676 close_nointr_nofail(fdf);
4677 close_nointr(fdt);
4678 unlink(to);
4679
4680 return r;
4681 }
4682
4683 if (n == 0)
4684 break;
4685
4686 errno = 0;
4687 k = loop_write(fdt, buf, n, false);
4688 if (n != k) {
4689 r = k < 0 ? k : (errno ? -errno : -EIO);
4690
4691 close_nointr_nofail(fdf);
4692 close_nointr(fdt);
4693
4694 unlink(to);
4695 return r;
4696 }
4697 }
4698
4699 close_nointr_nofail(fdf);
4700 r = close_nointr(fdt);
4701
4702 if (r < 0) {
4703 unlink(to);
4704 return r;
4705 }
4706
4707 return 0;
4708}
4709
424a19f8
LP
4710int symlink_atomic(const char *from, const char *to) {
4711 char *x;
4712 _cleanup_free_ char *t;
34ca941c
LP
4713 const char *fn;
4714 size_t k;
4715 unsigned long long ull;
4716 unsigned i;
4717 int r;
4718
4719 assert(from);
4720 assert(to);
4721
4722 t = new(char, strlen(to) + 1 + 16 + 1);
4723 if (!t)
4724 return -ENOMEM;
4725
9eb977db 4726 fn = path_get_file_name(to);
34ca941c
LP
4727 k = fn-to;
4728 memcpy(t, to, k);
4729 t[k] = '.';
4730 x = stpcpy(t+k+1, fn);
4731
4732 ull = random_ull();
4733 for (i = 0; i < 16; i++) {
4734 *(x++) = hexchar(ull & 0xF);
4735 ull >>= 4;
4736 }
4737
4738 *x = 0;
4739
424a19f8
LP
4740 if (symlink(from, t) < 0)
4741 return -errno;
34ca941c
LP
4742
4743 if (rename(t, to) < 0) {
4744 r = -errno;
4745 unlink(t);
34ca941c
LP
4746 return r;
4747 }
4748
424a19f8 4749 return 0;
34ca941c
LP
4750}
4751
4d6d6518
LP
4752bool display_is_local(const char *display) {
4753 assert(display);
4754
4755 return
4756 display[0] == ':' &&
4757 display[1] >= '0' &&
4758 display[1] <= '9';
4759}
4760
4761int socket_from_display(const char *display, char **path) {
4762 size_t k;
4763 char *f, *c;
4764
4765 assert(display);
4766 assert(path);
4767
4768 if (!display_is_local(display))
4769 return -EINVAL;
4770
4771 k = strspn(display+1, "0123456789");
4772
4773 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
4774 if (!f)
4775 return -ENOMEM;
4776
4777 c = stpcpy(f, "/tmp/.X11-unix/X");
4778 memcpy(c, display+1, k);
4779 c[k] = 0;
4780
4781 *path = f;
4782
4783 return 0;
4784}
4785
d05c5031
LP
4786int get_user_creds(
4787 const char **username,
4788 uid_t *uid, gid_t *gid,
4789 const char **home,
4790 const char **shell) {
4791
1cccf435 4792 struct passwd *p;
ddd88763 4793 uid_t u;
1cccf435
MV
4794
4795 assert(username);
4796 assert(*username);
1cccf435
MV
4797
4798 /* We enforce some special rules for uid=0: in order to avoid
4799 * NSS lookups for root we hardcode its data. */
4800
4801 if (streq(*username, "root") || streq(*username, "0")) {
4802 *username = "root";
4b67834e
LP
4803
4804 if (uid)
4805 *uid = 0;
4806
4807 if (gid)
4808 *gid = 0;
4809
4810 if (home)
4811 *home = "/root";
d05c5031
LP
4812
4813 if (shell)
4814 *shell = "/bin/sh";
4815
1cccf435
MV
4816 return 0;
4817 }
4818
ddd88763 4819 if (parse_uid(*username, &u) >= 0) {
1cccf435 4820 errno = 0;
ddd88763 4821 p = getpwuid(u);
1cccf435
MV
4822
4823 /* If there are multiple users with the same id, make
4824 * sure to leave $USER to the configured value instead
4825 * of the first occurrence in the database. However if
4826 * the uid was configured by a numeric uid, then let's
4827 * pick the real username from /etc/passwd. */
4828 if (p)
4829 *username = p->pw_name;
4830 } else {
4831 errno = 0;
4832 p = getpwnam(*username);
4833 }
4834
4835 if (!p)
4836 return errno != 0 ? -errno : -ESRCH;
4837
4b67834e
LP
4838 if (uid)
4839 *uid = p->pw_uid;
4840
4841 if (gid)
4842 *gid = p->pw_gid;
4843
4844 if (home)
4845 *home = p->pw_dir;
4846
d05c5031
LP
4847 if (shell)
4848 *shell = p->pw_shell;
4849
4b67834e
LP
4850 return 0;
4851}
4852
4853int get_group_creds(const char **groupname, gid_t *gid) {
4854 struct group *g;
4855 gid_t id;
4856
4857 assert(groupname);
4858
4859 /* We enforce some special rules for gid=0: in order to avoid
4860 * NSS lookups for root we hardcode its data. */
4861
4862 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4863 *groupname = "root";
4864
4865 if (gid)
4866 *gid = 0;
4867
4868 return 0;
4869 }
4870
4871 if (parse_gid(*groupname, &id) >= 0) {
4872 errno = 0;
4873 g = getgrgid(id);
4874
4875 if (g)
4876 *groupname = g->gr_name;
4877 } else {
4878 errno = 0;
4879 g = getgrnam(*groupname);
4880 }
4881
4882 if (!g)
4883 return errno != 0 ? -errno : -ESRCH;
4884
4885 if (gid)
4886 *gid = g->gr_gid;
4887
1cccf435
MV
4888 return 0;
4889}
4890
43673799
LP
4891int in_group(const char *name) {
4892 gid_t gid, *gids;
4893 int ngroups_max, r, i;
4894
4895 r = get_group_creds(&name, &gid);
4896 if (r < 0)
4897 return r;
4898
4899 if (getgid() == gid)
4900 return 1;
4901
4902 if (getegid() == gid)
4903 return 1;
4904
4905 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4906 assert(ngroups_max > 0);
4907
4908 gids = alloca(sizeof(gid_t) * ngroups_max);
4909
4910 r = getgroups(ngroups_max, gids);
4911 if (r < 0)
4912 return -errno;
4913
4914 for (i = 0; i < r; i++)
4915 if (gids[i] == gid)
4916 return 1;
4917
4918 return 0;
4919}
4920
8092a428
LP
4921int glob_exists(const char *path) {
4922 glob_t g;
4923 int r, k;
4924
4925 assert(path);
4926
4927 zero(g);
4928 errno = 0;
4929 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4930
4931 if (k == GLOB_NOMATCH)
4932 r = 0;
4933 else if (k == GLOB_NOSPACE)
4934 r = -ENOMEM;
4935 else if (k == 0)
4936 r = !strv_isempty(g.gl_pathv);
4937 else
4938 r = errno ? -errno : -EIO;
4939
4940 globfree(&g);
4941
4942 return r;
4943}
4944
83096483
LP
4945int dirent_ensure_type(DIR *d, struct dirent *de) {
4946 struct stat st;
4947
4948 assert(d);
4949 assert(de);
4950
4951 if (de->d_type != DT_UNKNOWN)
4952 return 0;
4953
4954 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4955 return -errno;
4956
4957 de->d_type =
4958 S_ISREG(st.st_mode) ? DT_REG :
4959 S_ISDIR(st.st_mode) ? DT_DIR :
4960 S_ISLNK(st.st_mode) ? DT_LNK :
4961 S_ISFIFO(st.st_mode) ? DT_FIFO :
4962 S_ISSOCK(st.st_mode) ? DT_SOCK :
4963 S_ISCHR(st.st_mode) ? DT_CHR :
4964 S_ISBLK(st.st_mode) ? DT_BLK :
4965 DT_UNKNOWN;
4966
4967 return 0;
4968}
4969
4970int in_search_path(const char *path, char **search) {
4971 char **i, *parent;
4972 int r;
4973
9eb977db 4974 r = path_get_parent(path, &parent);
83096483
LP
4975 if (r < 0)
4976 return r;
4977
4978 r = 0;
4979
4980 STRV_FOREACH(i, search) {
4981 if (path_equal(parent, *i)) {
4982 r = 1;
4983 break;
4984 }
4985 }
4986
4987 free(parent);
4988
4989 return r;
4990}
4991
034a2a52
LP
4992int get_files_in_directory(const char *path, char ***list) {
4993 DIR *d;
4994 int r = 0;
4995 unsigned n = 0;
4996 char **l = NULL;
4997
4998 assert(path);
d60ef526
LP
4999
5000 /* Returns all files in a directory in *list, and the number
5001 * of files as return value. If list is NULL returns only the
5002 * number */
034a2a52
LP
5003
5004 d = opendir(path);
8ea913b2
LP
5005 if (!d)
5006 return -errno;
5007
034a2a52 5008 for (;;) {
7d5e9c0f
LP
5009 struct dirent *de;
5010 union dirent_storage buf;
034a2a52
LP
5011 int k;
5012
7d5e9c0f 5013 k = readdir_r(d, &buf.de, &de);
034a2a52
LP
5014 if (k != 0) {
5015 r = -k;
5016 goto finish;
5017 }
5018
5019 if (!de)
5020 break;
5021
5022 dirent_ensure_type(d, de);
5023
5024 if (!dirent_is_file(de))
5025 continue;
5026
d60ef526
LP
5027 if (list) {
5028 if ((unsigned) r >= n) {
5029 char **t;
034a2a52 5030
d60ef526
LP
5031 n = MAX(16, 2*r);
5032 t = realloc(l, sizeof(char*) * n);
5033 if (!t) {
5034 r = -ENOMEM;
5035 goto finish;
5036 }
034a2a52 5037
d60ef526
LP
5038 l = t;
5039 }
034a2a52 5040
d60ef526 5041 assert((unsigned) r < n);
034a2a52 5042
d60ef526
LP
5043 l[r] = strdup(de->d_name);
5044 if (!l[r]) {
5045 r = -ENOMEM;
5046 goto finish;
5047 }
034a2a52 5048
d60ef526
LP
5049 l[++r] = NULL;
5050 } else
5051 r++;
034a2a52
LP
5052 }
5053
5054finish:
5055 if (d)
5056 closedir(d);
5057
d60ef526
LP
5058 if (r >= 0) {
5059 if (list)
5060 *list = l;
5061 } else
034a2a52
LP
5062 strv_free(l);
5063
5064 return r;
5065}
5066
b7def684 5067char *strjoin(const char *x, ...) {
911a4828
LP
5068 va_list ap;
5069 size_t l;
5070 char *r, *p;
5071
5072 va_start(ap, x);
5073
5074 if (x) {
5075 l = strlen(x);
5076
5077 for (;;) {
5078 const char *t;
040f18ea 5079 size_t n;
911a4828
LP
5080
5081 t = va_arg(ap, const char *);
5082 if (!t)
5083 break;
5084
040f18ea 5085 n = strlen(t);
e98055de
LN
5086 if (n > ((size_t) -1) - l) {
5087 va_end(ap);
040f18ea 5088 return NULL;
e98055de 5089 }
040f18ea
LP
5090
5091 l += n;
911a4828
LP
5092 }
5093 } else
5094 l = 0;
5095
5096 va_end(ap);
5097
5098 r = new(char, l+1);
5099 if (!r)
5100 return NULL;
5101
5102 if (x) {
5103 p = stpcpy(r, x);
5104
5105 va_start(ap, x);
5106
5107 for (;;) {
5108 const char *t;
5109
5110 t = va_arg(ap, const char *);
5111 if (!t)
5112 break;
5113
5114 p = stpcpy(p, t);
5115 }
8ea913b2
LP
5116
5117 va_end(ap);
911a4828
LP
5118 } else
5119 r[0] = 0;
5120
5121 return r;
5122}
5123
b636465b
LP
5124bool is_main_thread(void) {
5125 static __thread int cached = 0;
5126
5127 if (_unlikely_(cached == 0))
5128 cached = getpid() == gettid() ? 1 : -1;
5129
5130 return cached > 0;
5131}
5132
94959f0f
LP
5133int block_get_whole_disk(dev_t d, dev_t *ret) {
5134 char *p, *s;
5135 int r;
5136 unsigned n, m;
5137
5138 assert(ret);
5139
5140 /* If it has a queue this is good enough for us */
5141 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
5142 return -ENOMEM;
5143
5144 r = access(p, F_OK);
5145 free(p);
5146
5147 if (r >= 0) {
5148 *ret = d;
5149 return 0;
5150 }
5151
5152 /* If it is a partition find the originating device */
5153 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
5154 return -ENOMEM;
5155
5156 r = access(p, F_OK);
5157 free(p);
5158
5159 if (r < 0)
5160 return -ENOENT;
5161
5162 /* Get parent dev_t */
5163 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
5164 return -ENOMEM;
5165
5166 r = read_one_line_file(p, &s);
5167 free(p);
5168
5169 if (r < 0)
5170 return r;
5171
5172 r = sscanf(s, "%u:%u", &m, &n);
5173 free(s);
5174
5175 if (r != 2)
5176 return -EINVAL;
5177
5178 /* Only return this if it is really good enough for us. */
5179 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
5180 return -ENOMEM;
5181
5182 r = access(p, F_OK);
5183 free(p);
5184
5185 if (r >= 0) {
5186 *ret = makedev(m, n);
5187 return 0;
5188 }
5189
5190 return -ENOENT;
5191}
5192
8d53b453 5193int file_is_priv_sticky(const char *p) {
ad293f5a
LP
5194 struct stat st;
5195
5196 assert(p);
5197
5198 if (lstat(p, &st) < 0)
5199 return -errno;
5200
5201 return
8d53b453 5202 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
5203 (st.st_mode & S_ISVTX);
5204}
94959f0f 5205
f41607a6
LP
5206static const char *const ioprio_class_table[] = {
5207 [IOPRIO_CLASS_NONE] = "none",
5208 [IOPRIO_CLASS_RT] = "realtime",
5209 [IOPRIO_CLASS_BE] = "best-effort",
5210 [IOPRIO_CLASS_IDLE] = "idle"
5211};
5212
5213DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5214
5215static const char *const sigchld_code_table[] = {
5216 [CLD_EXITED] = "exited",
5217 [CLD_KILLED] = "killed",
5218 [CLD_DUMPED] = "dumped",
5219 [CLD_TRAPPED] = "trapped",
5220 [CLD_STOPPED] = "stopped",
5221 [CLD_CONTINUED] = "continued",
5222};
5223
5224DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5225
5226static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5227 [LOG_FAC(LOG_KERN)] = "kern",
5228 [LOG_FAC(LOG_USER)] = "user",
5229 [LOG_FAC(LOG_MAIL)] = "mail",
5230 [LOG_FAC(LOG_DAEMON)] = "daemon",
5231 [LOG_FAC(LOG_AUTH)] = "auth",
5232 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5233 [LOG_FAC(LOG_LPR)] = "lpr",
5234 [LOG_FAC(LOG_NEWS)] = "news",
5235 [LOG_FAC(LOG_UUCP)] = "uucp",
5236 [LOG_FAC(LOG_CRON)] = "cron",
5237 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5238 [LOG_FAC(LOG_FTP)] = "ftp",
5239 [LOG_FAC(LOG_LOCAL0)] = "local0",
5240 [LOG_FAC(LOG_LOCAL1)] = "local1",
5241 [LOG_FAC(LOG_LOCAL2)] = "local2",
5242 [LOG_FAC(LOG_LOCAL3)] = "local3",
5243 [LOG_FAC(LOG_LOCAL4)] = "local4",
5244 [LOG_FAC(LOG_LOCAL5)] = "local5",
5245 [LOG_FAC(LOG_LOCAL6)] = "local6",
5246 [LOG_FAC(LOG_LOCAL7)] = "local7"
5247};
5248
5249DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5250
5251static const char *const log_level_table[] = {
5252 [LOG_EMERG] = "emerg",
5253 [LOG_ALERT] = "alert",
5254 [LOG_CRIT] = "crit",
5255 [LOG_ERR] = "err",
5256 [LOG_WARNING] = "warning",
5257 [LOG_NOTICE] = "notice",
5258 [LOG_INFO] = "info",
5259 [LOG_DEBUG] = "debug"
5260};
5261
5262DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5263
5264static const char* const sched_policy_table[] = {
5265 [SCHED_OTHER] = "other",
5266 [SCHED_BATCH] = "batch",
5267 [SCHED_IDLE] = "idle",
5268 [SCHED_FIFO] = "fifo",
5269 [SCHED_RR] = "rr"
5270};
5271
5272DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5273
5274static const char* const rlimit_table[] = {
5275 [RLIMIT_CPU] = "LimitCPU",
5276 [RLIMIT_FSIZE] = "LimitFSIZE",
5277 [RLIMIT_DATA] = "LimitDATA",
5278 [RLIMIT_STACK] = "LimitSTACK",
5279 [RLIMIT_CORE] = "LimitCORE",
5280 [RLIMIT_RSS] = "LimitRSS",
5281 [RLIMIT_NOFILE] = "LimitNOFILE",
5282 [RLIMIT_AS] = "LimitAS",
5283 [RLIMIT_NPROC] = "LimitNPROC",
5284 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5285 [RLIMIT_LOCKS] = "LimitLOCKS",
5286 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5287 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5288 [RLIMIT_NICE] = "LimitNICE",
5289 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5290 [RLIMIT_RTTIME] = "LimitRTTIME"
5291};
5292
5293DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5294
5295static const char* const ip_tos_table[] = {
5296 [IPTOS_LOWDELAY] = "low-delay",
5297 [IPTOS_THROUGHPUT] = "throughput",
5298 [IPTOS_RELIABILITY] = "reliability",
5299 [IPTOS_LOWCOST] = "low-cost",
5300};
5301
5302DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5303
4e240ab0 5304static const char *const __signal_table[] = {
f41607a6
LP
5305 [SIGHUP] = "HUP",
5306 [SIGINT] = "INT",
5307 [SIGQUIT] = "QUIT",
5308 [SIGILL] = "ILL",
5309 [SIGTRAP] = "TRAP",
5310 [SIGABRT] = "ABRT",
5311 [SIGBUS] = "BUS",
5312 [SIGFPE] = "FPE",
5313 [SIGKILL] = "KILL",
5314 [SIGUSR1] = "USR1",
5315 [SIGSEGV] = "SEGV",
5316 [SIGUSR2] = "USR2",
5317 [SIGPIPE] = "PIPE",
5318 [SIGALRM] = "ALRM",
5319 [SIGTERM] = "TERM",
5320#ifdef SIGSTKFLT
5321 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5322#endif
5323 [SIGCHLD] = "CHLD",
5324 [SIGCONT] = "CONT",
5325 [SIGSTOP] = "STOP",
5326 [SIGTSTP] = "TSTP",
5327 [SIGTTIN] = "TTIN",
5328 [SIGTTOU] = "TTOU",
5329 [SIGURG] = "URG",
5330 [SIGXCPU] = "XCPU",
5331 [SIGXFSZ] = "XFSZ",
5332 [SIGVTALRM] = "VTALRM",
5333 [SIGPROF] = "PROF",
5334 [SIGWINCH] = "WINCH",
5335 [SIGIO] = "IO",
5336 [SIGPWR] = "PWR",
5337 [SIGSYS] = "SYS"
5338};
5339
4e240ab0
MS
5340DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5341
5342const char *signal_to_string(int signo) {
5343 static __thread char buf[12];
5344 const char *name;
5345
5346 name = __signal_to_string(signo);
5347 if (name)
5348 return name;
5349
5350 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
5351 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
5352 else
5353 snprintf(buf, sizeof(buf) - 1, "%d", signo);
5354 char_array_0(buf);
5355 return buf;
5356}
5357
5358int signal_from_string(const char *s) {
5359 int signo;
5360 int offset = 0;
5361 unsigned u;
5362
040f18ea 5363 signo = __signal_from_string(s);
4e240ab0
MS
5364 if (signo > 0)
5365 return signo;
5366
5367 if (startswith(s, "RTMIN+")) {
5368 s += 6;
5369 offset = SIGRTMIN;
5370 }
5371 if (safe_atou(s, &u) >= 0) {
5372 signo = (int) u + offset;
5373 if (signo > 0 && signo < _NSIG)
5374 return signo;
5375 }
5376 return -1;
5377}
65457142
FC
5378
5379bool kexec_loaded(void) {
5380 bool loaded = false;
5381 char *s;
5382
5383 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5384 if (s[0] == '1')
5385 loaded = true;
5386 free(s);
5387 }
5388 return loaded;
5389}
fb9de93d
LP
5390
5391int strdup_or_null(const char *a, char **b) {
5392 char *c;
5393
5394 assert(b);
5395
5396 if (!a) {
5397 *b = NULL;
5398 return 0;
5399 }
5400
5401 c = strdup(a);
5402 if (!c)
5403 return -ENOMEM;
5404
5405 *b = c;
5406 return 0;
5407}
64685e0c 5408
87d2c1ff
LP
5409int prot_from_flags(int flags) {
5410
5411 switch (flags & O_ACCMODE) {
5412
5413 case O_RDONLY:
5414 return PROT_READ;
5415
5416 case O_WRONLY:
5417 return PROT_WRITE;
5418
5419 case O_RDWR:
5420 return PROT_READ|PROT_WRITE;
5421
5422 default:
5423 return -EINVAL;
5424 }
7c99e0c1 5425}
689b9a22 5426
babfc091 5427char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5428 unsigned i;
babfc091
LP
5429
5430 static const struct {
5431 const char *suffix;
5432 off_t factor;
5433 } table[] = {
32895bb3
LP
5434 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5435 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5436 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5437 { "G", 1024ULL*1024ULL*1024ULL },
5438 { "M", 1024ULL*1024ULL },
5439 { "K", 1024ULL },
5440 };
5441
5442 for (i = 0; i < ELEMENTSOF(table); i++) {
5443
5444 if (t >= table[i].factor) {
5445 snprintf(buf, l,
5446 "%llu.%llu%s",
5447 (unsigned long long) (t / table[i].factor),
5448 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5449 table[i].suffix);
5450
5451 goto finish;
5452 }
5453 }
5454
5455 snprintf(buf, l, "%lluB", (unsigned long long) t);
5456
5457finish:
5458 buf[l-1] = 0;
5459 return buf;
5460
5461}
55d7bfc1
LP
5462
5463void* memdup(const void *p, size_t l) {
5464 void *r;
5465
5466 assert(p);
5467
5468 r = malloc(l);
5469 if (!r)
5470 return NULL;
5471
5472 memcpy(r, p, l);
5473 return r;
5474}
bb99a35a
LP
5475
5476int fd_inc_sndbuf(int fd, size_t n) {
5477 int r, value;
5478 socklen_t l = sizeof(value);
5479
5480 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
5481 if (r >= 0 &&
5482 l == sizeof(value) &&
5483 (size_t) value >= n*2)
5484 return 0;
5485
5486 value = (int) n;
5487 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
5488 if (r < 0)
5489 return -errno;
5490
5491 return 1;
5492}
5493
5494int fd_inc_rcvbuf(int fd, size_t n) {
5495 int r, value;
5496 socklen_t l = sizeof(value);
5497
5498 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
5499 if (r >= 0 &&
5500 l == sizeof(value) &&
5501 (size_t) value >= n*2)
5502 return 0;
5503
5504 value = (int) n;
5505 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
5506 if (r < 0)
5507 return -errno;
5508
5509 return 1;
5510}
6bb92a16 5511
9bdc770c 5512int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
5513 pid_t parent_pid, agent_pid;
5514 int fd;
5515 bool stdout_is_tty, stderr_is_tty;
5516 unsigned n, i;
5517 va_list ap;
5518 char **l;
5519
5520 assert(pid);
5521 assert(path);
5522
5523 parent_pid = getpid();
5524
5525 /* Spawns a temporary TTY agent, making sure it goes away when
5526 * we go away */
5527
5528 agent_pid = fork();
5529 if (agent_pid < 0)
5530 return -errno;
5531
5532 if (agent_pid != 0) {
5533 *pid = agent_pid;
5534 return 0;
5535 }
5536
5537 /* In the child:
5538 *
5539 * Make sure the agent goes away when the parent dies */
5540 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5541 _exit(EXIT_FAILURE);
5542
5543 /* Check whether our parent died before we were able
5544 * to set the death signal */
5545 if (getppid() != parent_pid)
5546 _exit(EXIT_SUCCESS);
5547
5548 /* Don't leak fds to the agent */
9bdc770c 5549 close_all_fds(except, n_except);
6bb92a16
LP
5550
5551 stdout_is_tty = isatty(STDOUT_FILENO);
5552 stderr_is_tty = isatty(STDERR_FILENO);
5553
5554 if (!stdout_is_tty || !stderr_is_tty) {
5555 /* Detach from stdout/stderr. and reopen
5556 * /dev/tty for them. This is important to
5557 * ensure that when systemctl is started via
5558 * popen() or a similar call that expects to
5559 * read EOF we actually do generate EOF and
5560 * not delay this indefinitely by because we
5561 * keep an unused copy of stdin around. */
5562 fd = open("/dev/tty", O_WRONLY);
5563 if (fd < 0) {
5564 log_error("Failed to open /dev/tty: %m");
5565 _exit(EXIT_FAILURE);
5566 }
5567
5568 if (!stdout_is_tty)
5569 dup2(fd, STDOUT_FILENO);
5570
5571 if (!stderr_is_tty)
5572 dup2(fd, STDERR_FILENO);
5573
5574 if (fd > 2)
5575 close(fd);
5576 }
5577
5578 /* Count arguments */
5579 va_start(ap, path);
5580 for (n = 0; va_arg(ap, char*); n++)
5581 ;
5582 va_end(ap);
5583
5584 /* Allocate strv */
5585 l = alloca(sizeof(char *) * (n + 1));
5586
5587 /* Fill in arguments */
5588 va_start(ap, path);
5589 for (i = 0; i <= n; i++)
5590 l[i] = va_arg(ap, char*);
5591 va_end(ap);
5592
5593 execv(path, l);
5594 _exit(EXIT_FAILURE);
5595}
68faf98c
LP
5596
5597int setrlimit_closest(int resource, const struct rlimit *rlim) {
5598 struct rlimit highest, fixed;
5599
5600 assert(rlim);
5601
5602 if (setrlimit(resource, rlim) >= 0)
5603 return 0;
5604
5605 if (errno != EPERM)
5606 return -errno;
5607
5608 /* So we failed to set the desired setrlimit, then let's try
5609 * to get as close as we can */
5610 assert_se(getrlimit(resource, &highest) == 0);
5611
5612 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5613 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5614
5615 if (setrlimit(resource, &fixed) < 0)
5616 return -errno;
5617
5618 return 0;
5619}
3d9a4122 5620
ab94af92
LP
5621int getenv_for_pid(pid_t pid, const char *field, char **_value) {
5622 char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
5623 int r;
5624 FILE *f;
5625 bool done = false;
5626 size_t l;
5627
5628 assert(field);
5629 assert(_value);
5630
5631 if (pid == 0)
5632 pid = getpid();
5633
5634 snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
5635 char_array_0(path);
5636
5637 f = fopen(path, "re");
5638 if (!f)
5639 return -errno;
5640
5641 l = strlen(field);
5642 r = 0;
5643
5644 do {
5645 char line[LINE_MAX];
5646 unsigned i;
5647
5648 for (i = 0; i < sizeof(line)-1; i++) {
5649 int c;
5650
5651 c = getc(f);
5652 if (_unlikely_(c == EOF)) {
5653 done = true;
5654 break;
5655 } else if (c == 0)
5656 break;
5657
5658 line[i] = c;
5659 }
5660 line[i] = 0;
5661
5662 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5663 value = strdup(line + l + 1);
5664 if (!value) {
5665 r = -ENOMEM;
5666 break;
5667 }
5668
5669 r = 1;
5670 break;
5671 }
5672
5673 } while (!done);
5674
5675 fclose(f);
5676
5677 if (r >= 0)
5678 *_value = value;
5679
5680 return r;
5681}
d889a206
LP
5682
5683int can_sleep(const char *type) {
e67f47e5 5684 char *w, *state;
d889a206 5685 size_t l, k;
d889a206 5686 int r;
e67f47e5 5687 _cleanup_free_ char *p = NULL;
d889a206
LP
5688
5689 assert(type);
5690
5691 r = read_one_line_file("/sys/power/state", &p);
5692 if (r < 0)
5693 return r == -ENOENT ? 0 : r;
5694
5695 k = strlen(type);
e67f47e5
LP
5696 FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
5697 if (l == k && memcmp(w, type, l) == 0)
5698 return true;
d889a206 5699
e67f47e5 5700 return false;
d889a206 5701}
49dbfa7b
LP
5702
5703bool is_valid_documentation_url(const char *url) {
5704 assert(url);
5705
5706 if (startswith(url, "http://") && url[7])
5707 return true;
5708
5709 if (startswith(url, "https://") && url[8])
5710 return true;
5711
5712 if (startswith(url, "file:") && url[5])
5713 return true;
5714
5715 if (startswith(url, "info:") && url[5])
5716 return true;
5717
5718 if (startswith(url, "man:") && url[4])
5719 return true;
5720
5721 return false;
5722}
9be346c9
HH
5723
5724bool in_initrd(void) {
a05f97b3 5725 static __thread int saved = -1;
825c6fe5 5726 struct statfs s;
8f33b5b8 5727
825c6fe5
LP
5728 if (saved >= 0)
5729 return saved;
5730
5731 /* We make two checks here:
5732 *
5733 * 1. the flag file /etc/initrd-release must exist
5734 * 2. the root file system must be a memory file system
5735 *
5736 * The second check is extra paranoia, since misdetecting an
5737 * initrd can have bad bad consequences due the initrd
5738 * emptying when transititioning to the main systemd.
5739 */
5740
5741 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5742 statfs("/", &s) >= 0 &&
5743 (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
9be346c9 5744
8f33b5b8 5745 return saved;
9be346c9 5746}
069cfc85
LP
5747
5748void warn_melody(void) {
e67f47e5 5749 _cleanup_close_ int fd = -1;
069cfc85
LP
5750
5751 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5752 if (fd < 0)
5753 return;
5754
040f18ea 5755 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5756
5757 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5758 usleep(125*USEC_PER_MSEC);
5759
5760 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5761 usleep(125*USEC_PER_MSEC);
5762
5763 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5764 usleep(125*USEC_PER_MSEC);
5765
5766 ioctl(fd, KIOCSOUND, 0);
069cfc85 5767}
cd3bd60a
LP
5768
5769int make_console_stdio(void) {
5770 int fd, r;
5771
5772 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5773
5774 fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
5775 if (fd < 0) {
5776 log_error("Failed to acquire terminal: %s", strerror(-fd));
5777 return fd;
5778 }
5779
5780 r = make_stdio(fd);
5781 if (r < 0) {
5782 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
5783 return r;
5784 }
5785
5786 return 0;
5787}
7c5f152a
LP
5788
5789int get_home_dir(char **_h) {
5790 char *h;
5791 const char *e;
5792 uid_t u;
5793 struct passwd *p;
5794
5795 assert(_h);
5796
5797 /* Take the user specified one */
5798 e = getenv("HOME");
5799 if (e) {
5800 h = strdup(e);
5801 if (!h)
5802 return -ENOMEM;
5803
5804 *_h = h;
5805 return 0;
5806 }
5807
5808 /* Hardcode home directory for root to avoid NSS */
5809 u = getuid();
5810 if (u == 0) {
5811 h = strdup("/root");
5812 if (!h)
5813 return -ENOMEM;
5814
5815 *_h = h;
5816 return 0;
5817 }
5818
5819 /* Check the database... */
5820 errno = 0;
5821 p = getpwuid(u);
5822 if (!p)
e67f47e5 5823 return errno ? -errno : -ESRCH;
7c5f152a
LP
5824
5825 if (!path_is_absolute(p->pw_dir))
5826 return -EINVAL;
5827
5828 h = strdup(p->pw_dir);
5829 if (!h)
5830 return -ENOMEM;
5831
5832 *_h = h;
5833 return 0;
5834}
5835
5836int get_shell(char **_sh) {
5837 char *sh;
5838 const char *e;
5839 uid_t u;
5840 struct passwd *p;
5841
5842 assert(_sh);
5843
5844 /* Take the user specified one */
5845 e = getenv("SHELL");
5846 if (e) {
5847 sh = strdup(e);
5848 if (!sh)
5849 return -ENOMEM;
5850
5851 *_sh = sh;
5852 return 0;
5853 }
5854
5855 /* Hardcode home directory for root to avoid NSS */
5856 u = getuid();
5857 if (u == 0) {
5858 sh = strdup("/bin/sh");
5859 if (!sh)
5860 return -ENOMEM;
5861
5862 *_sh = sh;
5863 return 0;
5864 }
5865
5866 /* Check the database... */
5867 errno = 0;
5868 p = getpwuid(u);
5869 if (!p)
5870 return errno ? -errno : -ESRCH;
5871
5872 if (!path_is_absolute(p->pw_shell))
5873 return -EINVAL;
5874
5875 sh = strdup(p->pw_shell);
5876 if (!sh)
5877 return -ENOMEM;
5878
5879 *_sh = sh;
5880 return 0;
5881}
2fbe635a
LP
5882
5883void freep(void *p) {
5884 free(*(void**) p);
5885}
5886
5887void fclosep(FILE **f) {
5888 if (*f)
5889 fclose(*f);
5890}
e67f47e5
LP
5891
5892void closep(int *fd) {
5893 if (*fd >= 0)
5894 close_nointr_nofail(*fd);
5895}
a05f97b3
LP
5896
5897void closedirp(DIR **d) {
5898 if (*d)
5899 closedir(*d);
5900}
25ea79fe
ZJS
5901
5902void umaskp(mode_t *u) {
5903 umask(*u);
5904}
0b507b17
LP
5905
5906bool filename_is_safe(const char *p) {
5907
5908 if (isempty(p))
5909 return false;
5910
5911 if (strchr(p, '/'))
5912 return false;
5913
5914 if (streq(p, "."))
5915 return false;
5916
5917 if (streq(p, ".."))
5918 return false;
5919
5920 if (strlen(p) > FILENAME_MAX)
5921 return false;
5922
5923 return true;
5924}
5925
5926bool string_is_safe(const char *p) {
5927 const char *t;
5928
5929 assert(p);
5930
5931 for (t = p; *t; t++) {
011afa76 5932 if (*t < ' ')
0b507b17
LP
5933 return false;
5934
011afa76 5935 if (strchr("\\\"\'", *t))
0b507b17
LP
5936 return false;
5937 }
5938
5939 return true;
5940}
cfbc22ab
LP
5941
5942int parse_timestamp(const char *t, usec_t *usec) {
5943 const char *k;
5944 struct tm tm, copy;
5945 time_t x;
5946 usec_t plus = 0, minus = 0, ret;
5947 int r;
5948
5949 /*
5950 * Allowed syntaxes:
5951 *
5952 * 2012-09-22 16:34:22
5953 * 2012-09-22 16:34 (seconds will be set to 0)
5954 * 2012-09-22 (time will be set to 00:00:00)
5955 * 16:34:22 (date will be set to today)
5956 * 16:34 (date will be set to today, seconds to 0)
5957 * now
5958 * yesterday (time is set to 00:00:00)
5959 * today (time is set to 00:00:00)
5960 * tomorrow (time is set to 00:00:00)
5961 * +5min
5962 * -5days
5963 *
5964 */
5965
5966 assert(t);
5967 assert(usec);
5968
5969 x = time(NULL);
5970 assert_se(localtime_r(&x, &tm));
5971
5972 if (streq(t, "now"))
5973 goto finish;
5974
5975 else if (streq(t, "today")) {
5976 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
5977 goto finish;
5978
5979 } else if (streq(t, "yesterday")) {
5980 tm.tm_mday --;
5981 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
5982 goto finish;
5983
5984 } else if (streq(t, "tomorrow")) {
5985 tm.tm_mday ++;
5986 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
5987 goto finish;
5988
5989 } else if (t[0] == '+') {
5990
5991 r = parse_usec(t+1, &plus);
5992 if (r < 0)
5993 return r;
5994
5995 goto finish;
5996 } else if (t[0] == '-') {
5997
5998 r = parse_usec(t+1, &minus);
5999 if (r < 0)
6000 return r;
6001
6002 goto finish;
6003 }
6004
6005 copy = tm;
6006 k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
6007 if (k && *k == 0)
6008 goto finish;
6009
6010 tm = copy;
6011 k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
6012 if (k && *k == 0)
6013 goto finish;
6014
6015 tm = copy;
6016 k = strptime(t, "%y-%m-%d %H:%M", &tm);
6017 if (k && *k == 0) {
6018 tm.tm_sec = 0;
6019 goto finish;
6020 }
6021
6022 tm = copy;
6023 k = strptime(t, "%Y-%m-%d %H:%M", &tm);
6024 if (k && *k == 0) {
6025 tm.tm_sec = 0;
6026 goto finish;
6027 }
6028
6029 tm = copy;
6030 k = strptime(t, "%y-%m-%d", &tm);
6031 if (k && *k == 0) {
6032 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
6033 goto finish;
6034 }
6035
6036 tm = copy;
6037 k = strptime(t, "%Y-%m-%d", &tm);
6038 if (k && *k == 0) {
6039 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
6040 goto finish;
6041 }
6042
6043 tm = copy;
6044 k = strptime(t, "%H:%M:%S", &tm);
6045 if (k && *k == 0)
6046 goto finish;
6047
6048 tm = copy;
6049 k = strptime(t, "%H:%M", &tm);
6050 if (k && *k == 0) {
6051 tm.tm_sec = 0;
6052 goto finish;
6053 }
6054
6055 return -EINVAL;
6056
6057finish:
6058 x = mktime(&tm);
6059 if (x == (time_t) -1)
6060 return -EINVAL;
6061
6062 ret = (usec_t) x * USEC_PER_SEC;
6063
6064 ret += plus;
6065 if (ret > minus)
6066 ret -= minus;
6067 else
6068 ret = 0;
6069
6070 *usec = ret;
6071
6072 return 0;
6073}