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