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