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