]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/util.c
dbus: properly pass capabilities
[thirdparty/systemd.git] / src / util.c
CommitLineData
60918275
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
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
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
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
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
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>
60918275
LP
51
52#include "macro.h"
53#include "util.h"
1dccbe19
LP
54#include "ioprio.h"
55#include "missing.h"
a9f5d454 56#include "log.h"
65d2ebdc 57#include "strv.h"
e51bc1a2 58#include "label.h"
56cf987f 59
e05797fb
LP
60bool streq_ptr(const char *a, const char *b) {
61
62 /* Like streq(), but tries to make sense of NULL pointers */
63
64 if (a && b)
65 return streq(a, b);
66
67 if (!a && !b)
68 return true;
69
70 return false;
71}
72
47be870b 73usec_t now(clockid_t clock_id) {
60918275
LP
74 struct timespec ts;
75
47be870b 76 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
77
78 return timespec_load(&ts);
79}
80
63983207 81dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
871d7de4
LP
82 assert(ts);
83
84 ts->realtime = now(CLOCK_REALTIME);
85 ts->monotonic = now(CLOCK_MONOTONIC);
86
87 return ts;
88}
89
60918275
LP
90usec_t timespec_load(const struct timespec *ts) {
91 assert(ts);
92
93 return
94 (usec_t) ts->tv_sec * USEC_PER_SEC +
95 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
96}
97
98struct timespec *timespec_store(struct timespec *ts, usec_t u) {
99 assert(ts);
100
101 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
102 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
103
104 return ts;
105}
106
107usec_t timeval_load(const struct timeval *tv) {
108 assert(tv);
109
110 return
111 (usec_t) tv->tv_sec * USEC_PER_SEC +
112 (usec_t) tv->tv_usec;
113}
114
115struct timeval *timeval_store(struct timeval *tv, usec_t u) {
116 assert(tv);
117
118 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
119 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
120
121 return tv;
122}
123
124bool endswith(const char *s, const char *postfix) {
125 size_t sl, pl;
126
127 assert(s);
128 assert(postfix);
129
130 sl = strlen(s);
131 pl = strlen(postfix);
132
d4d0d4db
LP
133 if (pl == 0)
134 return true;
135
60918275
LP
136 if (sl < pl)
137 return false;
138
139 return memcmp(s + sl - pl, postfix, pl) == 0;
140}
141
142bool startswith(const char *s, const char *prefix) {
143 size_t sl, pl;
144
145 assert(s);
146 assert(prefix);
147
148 sl = strlen(s);
149 pl = strlen(prefix);
150
d4d0d4db
LP
151 if (pl == 0)
152 return true;
153
60918275
LP
154 if (sl < pl)
155 return false;
156
157 return memcmp(s, prefix, pl) == 0;
158}
159
3177a7fa
MAP
160bool startswith_no_case(const char *s, const char *prefix) {
161 size_t sl, pl;
162 unsigned i;
163
164 assert(s);
165 assert(prefix);
166
167 sl = strlen(s);
168 pl = strlen(prefix);
169
170 if (pl == 0)
171 return true;
172
173 if (sl < pl)
174 return false;
175
176 for(i = 0; i < pl; ++i) {
177 if (tolower(s[i]) != tolower(prefix[i]))
178 return false;
179 }
180
181 return true;
182}
183
79d6d816
LP
184bool first_word(const char *s, const char *word) {
185 size_t sl, wl;
186
187 assert(s);
188 assert(word);
189
190 sl = strlen(s);
191 wl = strlen(word);
192
193 if (sl < wl)
194 return false;
195
d4d0d4db
LP
196 if (wl == 0)
197 return true;
198
79d6d816
LP
199 if (memcmp(s, word, wl) != 0)
200 return false;
201
d4d0d4db
LP
202 return s[wl] == 0 ||
203 strchr(WHITESPACE, s[wl]);
79d6d816
LP
204}
205
42f4e3c4 206int close_nointr(int fd) {
60918275
LP
207 assert(fd >= 0);
208
209 for (;;) {
210 int r;
211
212 if ((r = close(fd)) >= 0)
213 return r;
214
215 if (errno != EINTR)
216 return r;
217 }
218}
85261803 219
85f136b5 220void close_nointr_nofail(int fd) {
80876c20 221 int saved_errno = errno;
85f136b5
LP
222
223 /* like close_nointr() but cannot fail, and guarantees errno
224 * is unchanged */
225
226 assert_se(close_nointr(fd) == 0);
80876c20
LP
227
228 errno = saved_errno;
85f136b5
LP
229}
230
5b6319dc
LP
231void close_many(const int fds[], unsigned n_fd) {
232 unsigned i;
233
234 for (i = 0; i < n_fd; i++)
235 close_nointr_nofail(fds[i]);
236}
237
85261803
LP
238int parse_boolean(const char *v) {
239 assert(v);
240
44d8db9e 241 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 242 return 1;
44d8db9e 243 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
244 return 0;
245
246 return -EINVAL;
247}
248
3ba686c1
LP
249int parse_pid(const char *s, pid_t* ret_pid) {
250 unsigned long ul;
251 pid_t pid;
252 int r;
253
254 assert(s);
255 assert(ret_pid);
256
257 if ((r = safe_atolu(s, &ul)) < 0)
258 return r;
259
260 pid = (pid_t) ul;
261
262 if ((unsigned long) pid != ul)
263 return -ERANGE;
264
265 if (pid <= 0)
266 return -ERANGE;
267
268 *ret_pid = pid;
269 return 0;
270}
271
85261803
LP
272int safe_atou(const char *s, unsigned *ret_u) {
273 char *x = NULL;
034c6ed7 274 unsigned long l;
85261803
LP
275
276 assert(s);
277 assert(ret_u);
278
279 errno = 0;
280 l = strtoul(s, &x, 0);
281
282 if (!x || *x || errno)
283 return errno ? -errno : -EINVAL;
284
034c6ed7 285 if ((unsigned long) (unsigned) l != l)
85261803
LP
286 return -ERANGE;
287
288 *ret_u = (unsigned) l;
289 return 0;
290}
291
292int safe_atoi(const char *s, int *ret_i) {
293 char *x = NULL;
034c6ed7 294 long l;
85261803
LP
295
296 assert(s);
297 assert(ret_i);
298
299 errno = 0;
300 l = strtol(s, &x, 0);
301
302 if (!x || *x || errno)
303 return errno ? -errno : -EINVAL;
304
034c6ed7 305 if ((long) (int) l != l)
85261803
LP
306 return -ERANGE;
307
034c6ed7
LP
308 *ret_i = (int) l;
309 return 0;
310}
311
034c6ed7
LP
312int safe_atollu(const char *s, long long unsigned *ret_llu) {
313 char *x = NULL;
314 unsigned long long l;
315
316 assert(s);
317 assert(ret_llu);
318
319 errno = 0;
320 l = strtoull(s, &x, 0);
321
322 if (!x || *x || errno)
323 return errno ? -errno : -EINVAL;
324
325 *ret_llu = l;
326 return 0;
327}
328
329int safe_atolli(const char *s, long long int *ret_lli) {
330 char *x = NULL;
331 long long l;
332
333 assert(s);
334 assert(ret_lli);
335
336 errno = 0;
337 l = strtoll(s, &x, 0);
338
339 if (!x || *x || errno)
340 return errno ? -errno : -EINVAL;
341
342 *ret_lli = l;
85261803
LP
343 return 0;
344}
a41e8209 345
a41e8209 346/* Split a string into words. */
65d2ebdc 347char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
348 char *current;
349
350 current = *state ? *state : (char*) c;
351
352 if (!*current || *c == 0)
353 return NULL;
354
65d2ebdc
LP
355 current += strspn(current, separator);
356 *l = strcspn(current, separator);
82919e3d
LP
357 *state = current+*l;
358
359 return (char*) current;
360}
361
034c6ed7
LP
362/* Split a string into words, but consider strings enclosed in '' and
363 * "" as words even if they include spaces. */
364char *split_quoted(const char *c, size_t *l, char **state) {
0bab36f2
LP
365 char *current, *e;
366 bool escaped = false;
034c6ed7
LP
367
368 current = *state ? *state : (char*) c;
369
370 if (!*current || *c == 0)
371 return NULL;
372
373 current += strspn(current, WHITESPACE);
374
375 if (*current == '\'') {
376 current ++;
034c6ed7 377
0bab36f2
LP
378 for (e = current; *e; e++) {
379 if (escaped)
380 escaped = false;
381 else if (*e == '\\')
382 escaped = true;
383 else if (*e == '\'')
384 break;
385 }
386
387 *l = e-current;
388 *state = *e == 0 ? e : e+1;
034c6ed7
LP
389 } else if (*current == '\"') {
390 current ++;
034c6ed7 391
0bab36f2
LP
392 for (e = current; *e; e++) {
393 if (escaped)
394 escaped = false;
395 else if (*e == '\\')
396 escaped = true;
397 else if (*e == '\"')
398 break;
399 }
400
401 *l = e-current;
402 *state = *e == 0 ? e : e+1;
034c6ed7 403 } else {
0bab36f2
LP
404 for (e = current; *e; e++) {
405 if (escaped)
406 escaped = false;
407 else if (*e == '\\')
408 escaped = true;
409 else if (strchr(WHITESPACE, *e))
410 break;
411 }
412 *l = e-current;
413 *state = e;
034c6ed7
LP
414 }
415
416 return (char*) current;
417}
418
65d2ebdc
LP
419char **split_path_and_make_absolute(const char *p) {
420 char **l;
421 assert(p);
422
423 if (!(l = strv_split(p, ":")))
424 return NULL;
425
426 if (!strv_path_make_absolute_cwd(l)) {
427 strv_free(l);
428 return NULL;
429 }
430
431 return l;
432}
433
034c6ed7
LP
434int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
435 int r;
436 FILE *f;
437 char fn[132], line[256], *p;
bb00e604 438 long unsigned ppid;
034c6ed7
LP
439
440 assert(pid >= 0);
441 assert(_ppid);
442
bb00e604 443 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
034c6ed7
LP
444 fn[sizeof(fn)-1] = 0;
445
446 if (!(f = fopen(fn, "r")))
447 return -errno;
448
449 if (!(fgets(line, sizeof(line), f))) {
450 r = -errno;
451 fclose(f);
452 return r;
453 }
454
455 fclose(f);
456
457 /* Let's skip the pid and comm fields. The latter is enclosed
458 * in () but does not escape any () in its value, so let's
459 * skip over it manually */
460
461 if (!(p = strrchr(line, ')')))
462 return -EIO;
463
464 p++;
465
466 if (sscanf(p, " "
467 "%*c " /* state */
bb00e604 468 "%lu ", /* ppid */
034c6ed7
LP
469 &ppid) != 1)
470 return -EIO;
471
bb00e604 472 if ((long unsigned) (pid_t) ppid != ppid)
034c6ed7
LP
473 return -ERANGE;
474
475 *_ppid = (pid_t) ppid;
476
477 return 0;
478}
479
480int write_one_line_file(const char *fn, const char *line) {
481 FILE *f;
482 int r;
483
484 assert(fn);
485 assert(line);
486
487 if (!(f = fopen(fn, "we")))
488 return -errno;
489
490 if (fputs(line, f) < 0) {
491 r = -errno;
492 goto finish;
493 }
494
495 r = 0;
496finish:
497 fclose(f);
498 return r;
499}
500
501int read_one_line_file(const char *fn, char **line) {
502 FILE *f;
503 int r;
11316633 504 char t[2048], *c;
034c6ed7
LP
505
506 assert(fn);
507 assert(line);
508
509 if (!(f = fopen(fn, "re")))
510 return -errno;
511
512 if (!(fgets(t, sizeof(t), f))) {
513 r = -errno;
514 goto finish;
515 }
516
517 if (!(c = strdup(t))) {
518 r = -ENOMEM;
519 goto finish;
520 }
521
522 *line = c;
523 r = 0;
524
525finish:
526 fclose(f);
527 return r;
528}
44d8db9e 529
7072ced8
LP
530char *truncate_nl(char *s) {
531 assert(s);
532
533 s[strcspn(s, NEWLINE)] = 0;
534 return s;
535}
536
537int get_process_name(pid_t pid, char **name) {
538 char *p;
539 int r;
540
541 assert(pid >= 1);
542 assert(name);
543
bb00e604 544 if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
7072ced8
LP
545 return -ENOMEM;
546
547 r = read_one_line_file(p, name);
548 free(p);
549
550 if (r < 0)
551 return r;
552
553 truncate_nl(*name);
554 return 0;
555}
556
c59760ee
LP
557int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
558 char *p, *r, *k;
559 int c;
560 bool space = false;
561 size_t left;
562 FILE *f;
563
564 assert(pid >= 1);
565 assert(max_length > 0);
566 assert(line);
567
568 if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
569 return -ENOMEM;
570
571 f = fopen(p, "r");
572 free(p);
573
574 if (!f)
575 return -errno;
576
577 if (!(r = new(char, max_length))) {
578 fclose(f);
579 return -ENOMEM;
580 }
581
582 k = r;
583 left = max_length;
584 while ((c = getc(f)) != EOF) {
585
586 if (isprint(c)) {
587 if (space) {
588 if (left <= 4)
589 break;
590
591 *(k++) = ' ';
057fbb58 592 left--;
c59760ee
LP
593 space = false;
594 }
595
596 if (left <= 4)
597 break;
598
599 *(k++) = (char) c;
057fbb58 600 left--;
c59760ee
LP
601 } else
602 space = true;
603 }
604
605 if (left <= 4) {
606 size_t n = MIN(left-1, 3U);
607 memcpy(k, "...", n);
608 k[n] = 0;
609 } else
610 *k = 0;
611
612 fclose(f);
613
35d2e7ec
LP
614 /* Kernel threads have no argv[] */
615 if (r[0] == 0) {
616 char *t;
617 int h;
618
619 free(r);
620
621 if ((h = get_process_name(pid, &t)) < 0)
622 return h;
623
624 h = asprintf(&r, "[%s]", t);
625 free(t);
626
627 if (h < 0)
628 return -ENOMEM;
629 }
fa776d8e 630
c59760ee
LP
631 *line = r;
632 return 0;
633}
634
fab56fc5
LP
635char *strnappend(const char *s, const char *suffix, size_t b) {
636 size_t a;
44d8db9e
LP
637 char *r;
638
fab56fc5
LP
639 if (!s && !suffix)
640 return strdup("");
641
642 if (!s)
643 return strndup(suffix, b);
644
645 if (!suffix)
646 return strdup(s);
647
44d8db9e
LP
648 assert(s);
649 assert(suffix);
650
651 a = strlen(s);
44d8db9e
LP
652
653 if (!(r = new(char, a+b+1)))
654 return NULL;
655
656 memcpy(r, s, a);
657 memcpy(r+a, suffix, b);
658 r[a+b] = 0;
659
660 return r;
661}
87f0e418 662
fab56fc5
LP
663char *strappend(const char *s, const char *suffix) {
664 return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
665}
666
87f0e418
LP
667int readlink_malloc(const char *p, char **r) {
668 size_t l = 100;
669
670 assert(p);
671 assert(r);
672
673 for (;;) {
674 char *c;
675 ssize_t n;
676
677 if (!(c = new(char, l)))
678 return -ENOMEM;
679
680 if ((n = readlink(p, c, l-1)) < 0) {
681 int ret = -errno;
682 free(c);
683 return ret;
684 }
685
686 if ((size_t) n < l-1) {
687 c[n] = 0;
688 *r = c;
689 return 0;
690 }
691
692 free(c);
693 l *= 2;
694 }
695}
696
2c7108c4
LP
697int readlink_and_make_absolute(const char *p, char **r) {
698 char *target, *k;
699 int j;
700
701 assert(p);
702 assert(r);
703
704 if ((j = readlink_malloc(p, &target)) < 0)
705 return j;
706
707 k = file_in_same_dir(p, target);
708 free(target);
709
710 if (!k)
711 return -ENOMEM;
712
713 *r = k;
714 return 0;
715}
716
35d2e7ec
LP
717int parent_of_path(const char *path, char **_r) {
718 const char *e, *a = NULL, *b = NULL, *p;
719 char *r;
720 bool slash = false;
721
722 assert(path);
723 assert(_r);
724
725 if (!*path)
726 return -EINVAL;
727
728 for (e = path; *e; e++) {
729
730 if (!slash && *e == '/') {
731 a = b;
732 b = e;
733 slash = true;
734 } else if (slash && *e != '/')
735 slash = false;
736 }
737
738 if (*(e-1) == '/')
739 p = a;
740 else
741 p = b;
742
743 if (!p)
744 return -EINVAL;
745
746 if (p == path)
747 r = strdup("/");
748 else
749 r = strndup(path, p-path);
750
751 if (!r)
752 return -ENOMEM;
753
754 *_r = r;
755 return 0;
756}
757
758
87f0e418
LP
759char *file_name_from_path(const char *p) {
760 char *r;
761
762 assert(p);
763
764 if ((r = strrchr(p, '/')))
765 return r + 1;
766
767 return (char*) p;
768}
0301abf4
LP
769
770bool path_is_absolute(const char *p) {
771 assert(p);
772
773 return p[0] == '/';
774}
775
776bool is_path(const char *p) {
777
778 return !!strchr(p, '/');
779}
780
781char *path_make_absolute(const char *p, const char *prefix) {
782 char *r;
783
784 assert(p);
785
65d2ebdc
LP
786 /* Makes every item in the list an absolute path by prepending
787 * the prefix, if specified and necessary */
788
0301abf4
LP
789 if (path_is_absolute(p) || !prefix)
790 return strdup(p);
791
792 if (asprintf(&r, "%s/%s", prefix, p) < 0)
793 return NULL;
794
795 return r;
796}
2a987ee8 797
65d2ebdc
LP
798char *path_make_absolute_cwd(const char *p) {
799 char *cwd, *r;
800
801 assert(p);
802
803 /* Similar to path_make_absolute(), but prefixes with the
804 * current working directory. */
805
806 if (path_is_absolute(p))
807 return strdup(p);
808
809 if (!(cwd = get_current_dir_name()))
810 return NULL;
811
812 r = path_make_absolute(p, cwd);
813 free(cwd);
814
815 return r;
816}
817
818char **strv_path_make_absolute_cwd(char **l) {
819 char **s;
820
821 /* Goes through every item in the string list and makes it
822 * absolute. This works in place and won't rollback any
823 * changes on failure. */
824
825 STRV_FOREACH(s, l) {
826 char *t;
827
828 if (!(t = path_make_absolute_cwd(*s)))
829 return NULL;
830
831 free(*s);
832 *s = t;
833 }
834
835 return l;
836}
837
c3f6d675
LP
838char **strv_path_canonicalize(char **l) {
839 char **s;
840 unsigned k = 0;
841 bool enomem = false;
842
843 if (strv_isempty(l))
844 return l;
845
846 /* Goes through every item in the string list and canonicalize
847 * the path. This works in place and won't rollback any
848 * changes on failure. */
849
850 STRV_FOREACH(s, l) {
851 char *t, *u;
852
853 t = path_make_absolute_cwd(*s);
854 free(*s);
855
856 if (!t) {
857 enomem = true;
858 continue;
859 }
860
861 errno = 0;
862 u = canonicalize_file_name(t);
863 free(t);
864
865 if (!u) {
866 if (errno == ENOMEM || !errno)
867 enomem = true;
868
869 continue;
870 }
871
872 l[k++] = u;
873 }
874
875 l[k] = NULL;
876
877 if (enomem)
878 return NULL;
879
880 return l;
881}
882
2a987ee8
LP
883int reset_all_signal_handlers(void) {
884 int sig;
885
886 for (sig = 1; sig < _NSIG; sig++) {
887 struct sigaction sa;
888
889 if (sig == SIGKILL || sig == SIGSTOP)
890 continue;
891
892 zero(sa);
893 sa.sa_handler = SIG_DFL;
431c32bf 894 sa.sa_flags = SA_RESTART;
2a987ee8
LP
895
896 /* On Linux the first two RT signals are reserved by
897 * glibc, and sigaction() will return EINVAL for them. */
898 if ((sigaction(sig, &sa, NULL) < 0))
899 if (errno != EINVAL)
900 return -errno;
901 }
902
8e274523 903 return 0;
2a987ee8 904}
4a72ff34
LP
905
906char *strstrip(char *s) {
907 char *e, *l = NULL;
908
909 /* Drops trailing whitespace. Modifies the string in
910 * place. Returns pointer to first non-space character */
911
912 s += strspn(s, WHITESPACE);
913
914 for (e = s; *e; e++)
915 if (!strchr(WHITESPACE, *e))
916 l = e;
917
918 if (l)
919 *(l+1) = 0;
920 else
921 *s = 0;
922
923 return s;
4a72ff34
LP
924}
925
ee9b5e01
LP
926char *delete_chars(char *s, const char *bad) {
927 char *f, *t;
928
929 /* Drops all whitespace, regardless where in the string */
930
931 for (f = s, t = s; *f; f++) {
932 if (strchr(bad, *f))
933 continue;
934
935 *(t++) = *f;
936 }
937
938 *t = 0;
939
940 return s;
941}
942
4a72ff34
LP
943char *file_in_same_dir(const char *path, const char *filename) {
944 char *e, *r;
945 size_t k;
946
947 assert(path);
948 assert(filename);
949
950 /* This removes the last component of path and appends
951 * filename, unless the latter is absolute anyway or the
952 * former isn't */
953
954 if (path_is_absolute(filename))
955 return strdup(filename);
956
957 if (!(e = strrchr(path, '/')))
958 return strdup(filename);
959
960 k = strlen(filename);
961 if (!(r = new(char, e-path+1+k+1)))
962 return NULL;
963
964 memcpy(r, path, e-path+1);
965 memcpy(r+(e-path)+1, filename, k+1);
966
967 return r;
968}
fb624d04 969
8c6db833
LP
970int safe_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
971 struct stat st;
972
56cf987f 973 if (label_mkdir(path, mode) >= 0)
8c6db833
LP
974 if (chmod_and_chown(path, mode, uid, gid) < 0)
975 return -errno;
976
977 if (lstat(path, &st) < 0)
978 return -errno;
979
980 if ((st.st_mode & 0777) != mode ||
981 st.st_uid != uid ||
982 st.st_gid != gid ||
983 !S_ISDIR(st.st_mode)) {
984 errno = EEXIST;
985 return -errno;
986 }
987
988 return 0;
989}
990
991
a9f5d454
LP
992int mkdir_parents(const char *path, mode_t mode) {
993 const char *p, *e;
994
995 assert(path);
996
997 /* Creates every parent directory in the path except the last
998 * component. */
999
1000 p = path + strspn(path, "/");
1001 for (;;) {
1002 int r;
1003 char *t;
1004
1005 e = p + strcspn(p, "/");
1006 p = e + strspn(e, "/");
1007
1008 /* Is this the last component? If so, then we're
1009 * done */
1010 if (*p == 0)
1011 return 0;
1012
1013 if (!(t = strndup(path, e - path)))
1014 return -ENOMEM;
1015
56cf987f 1016 r = label_mkdir(t, mode);
a9f5d454
LP
1017 free(t);
1018
1019 if (r < 0 && errno != EEXIST)
1020 return -errno;
1021 }
1022}
1023
bbd67135
LP
1024int mkdir_p(const char *path, mode_t mode) {
1025 int r;
1026
1027 /* Like mkdir -p */
1028
1029 if ((r = mkdir_parents(path, mode)) < 0)
1030 return r;
1031
56cf987f 1032 if (label_mkdir(path, mode) < 0 && errno != EEXIST)
bbd67135
LP
1033 return -errno;
1034
1035 return 0;
1036}
1037
c32dd69b
LP
1038int rmdir_parents(const char *path, const char *stop) {
1039 size_t l;
1040 int r = 0;
1041
1042 assert(path);
1043 assert(stop);
1044
1045 l = strlen(path);
1046
1047 /* Skip trailing slashes */
1048 while (l > 0 && path[l-1] == '/')
1049 l--;
1050
1051 while (l > 0) {
1052 char *t;
1053
1054 /* Skip last component */
1055 while (l > 0 && path[l-1] != '/')
1056 l--;
1057
1058 /* Skip trailing slashes */
1059 while (l > 0 && path[l-1] == '/')
1060 l--;
1061
1062 if (l <= 0)
1063 break;
1064
1065 if (!(t = strndup(path, l)))
1066 return -ENOMEM;
1067
1068 if (path_startswith(stop, t)) {
1069 free(t);
1070 return 0;
1071 }
1072
1073 r = rmdir(t);
1074 free(t);
1075
1076 if (r < 0)
1077 if (errno != ENOENT)
1078 return -errno;
1079 }
1080
1081 return 0;
1082}
1083
1084
fb624d04
LP
1085char hexchar(int x) {
1086 static const char table[16] = "0123456789abcdef";
1087
1088 return table[x & 15];
1089}
4fe88d28
LP
1090
1091int unhexchar(char c) {
1092
1093 if (c >= '0' && c <= '9')
1094 return c - '0';
1095
1096 if (c >= 'a' && c <= 'f')
ea430986 1097 return c - 'a' + 10;
4fe88d28
LP
1098
1099 if (c >= 'A' && c <= 'F')
ea430986 1100 return c - 'A' + 10;
4fe88d28
LP
1101
1102 return -1;
1103}
1104
1105char octchar(int x) {
1106 return '0' + (x & 7);
1107}
1108
1109int unoctchar(char c) {
1110
1111 if (c >= '0' && c <= '7')
1112 return c - '0';
1113
1114 return -1;
1115}
1116
5af98f82
LP
1117char decchar(int x) {
1118 return '0' + (x % 10);
1119}
1120
1121int undecchar(char c) {
1122
1123 if (c >= '0' && c <= '9')
1124 return c - '0';
1125
1126 return -1;
1127}
1128
4fe88d28
LP
1129char *cescape(const char *s) {
1130 char *r, *t;
1131 const char *f;
1132
1133 assert(s);
1134
1135 /* Does C style string escaping. */
1136
1137 if (!(r = new(char, strlen(s)*4 + 1)))
1138 return NULL;
1139
1140 for (f = s, t = r; *f; f++)
1141
1142 switch (*f) {
1143
1144 case '\a':
1145 *(t++) = '\\';
1146 *(t++) = 'a';
1147 break;
1148 case '\b':
1149 *(t++) = '\\';
1150 *(t++) = 'b';
1151 break;
1152 case '\f':
1153 *(t++) = '\\';
1154 *(t++) = 'f';
1155 break;
1156 case '\n':
1157 *(t++) = '\\';
1158 *(t++) = 'n';
1159 break;
1160 case '\r':
1161 *(t++) = '\\';
1162 *(t++) = 'r';
1163 break;
1164 case '\t':
1165 *(t++) = '\\';
1166 *(t++) = 't';
1167 break;
1168 case '\v':
1169 *(t++) = '\\';
1170 *(t++) = 'v';
1171 break;
1172 case '\\':
1173 *(t++) = '\\';
1174 *(t++) = '\\';
1175 break;
1176 case '"':
1177 *(t++) = '\\';
1178 *(t++) = '"';
1179 break;
1180 case '\'':
1181 *(t++) = '\\';
1182 *(t++) = '\'';
1183 break;
1184
1185 default:
1186 /* For special chars we prefer octal over
1187 * hexadecimal encoding, simply because glib's
1188 * g_strescape() does the same */
1189 if ((*f < ' ') || (*f >= 127)) {
1190 *(t++) = '\\';
1191 *(t++) = octchar((unsigned char) *f >> 6);
1192 *(t++) = octchar((unsigned char) *f >> 3);
1193 *(t++) = octchar((unsigned char) *f);
1194 } else
1195 *(t++) = *f;
1196 break;
1197 }
1198
1199 *t = 0;
1200
1201 return r;
1202}
1203
6febfd0d 1204char *cunescape_length(const char *s, size_t length) {
4fe88d28
LP
1205 char *r, *t;
1206 const char *f;
1207
1208 assert(s);
1209
1210 /* Undoes C style string escaping */
1211
6febfd0d 1212 if (!(r = new(char, length+1)))
4fe88d28
LP
1213 return r;
1214
6febfd0d 1215 for (f = s, t = r; f < s + length; f++) {
4fe88d28
LP
1216
1217 if (*f != '\\') {
1218 *(t++) = *f;
1219 continue;
1220 }
1221
1222 f++;
1223
1224 switch (*f) {
1225
1226 case 'a':
1227 *(t++) = '\a';
1228 break;
1229 case 'b':
1230 *(t++) = '\b';
1231 break;
1232 case 'f':
1233 *(t++) = '\f';
1234 break;
1235 case 'n':
1236 *(t++) = '\n';
1237 break;
1238 case 'r':
1239 *(t++) = '\r';
1240 break;
1241 case 't':
1242 *(t++) = '\t';
1243 break;
1244 case 'v':
1245 *(t++) = '\v';
1246 break;
1247 case '\\':
1248 *(t++) = '\\';
1249 break;
1250 case '"':
1251 *(t++) = '"';
1252 break;
1253 case '\'':
1254 *(t++) = '\'';
1255 break;
1256
e167fb86
LP
1257 case 's':
1258 /* This is an extension of the XDG syntax files */
1259 *(t++) = ' ';
1260 break;
1261
4fe88d28
LP
1262 case 'x': {
1263 /* hexadecimal encoding */
1264 int a, b;
1265
1266 if ((a = unhexchar(f[1])) < 0 ||
1267 (b = unhexchar(f[2])) < 0) {
1268 /* Invalid escape code, let's take it literal then */
1269 *(t++) = '\\';
1270 *(t++) = 'x';
1271 } else {
1272 *(t++) = (char) ((a << 4) | b);
1273 f += 2;
1274 }
1275
1276 break;
1277 }
1278
1279 case '0':
1280 case '1':
1281 case '2':
1282 case '3':
1283 case '4':
1284 case '5':
1285 case '6':
1286 case '7': {
1287 /* octal encoding */
1288 int a, b, c;
1289
1290 if ((a = unoctchar(f[0])) < 0 ||
1291 (b = unoctchar(f[1])) < 0 ||
1292 (c = unoctchar(f[2])) < 0) {
1293 /* Invalid escape code, let's take it literal then */
1294 *(t++) = '\\';
1295 *(t++) = f[0];
1296 } else {
1297 *(t++) = (char) ((a << 6) | (b << 3) | c);
1298 f += 2;
1299 }
1300
1301 break;
1302 }
1303
1304 case 0:
1305 /* premature end of string.*/
1306 *(t++) = '\\';
1307 goto finish;
1308
1309 default:
1310 /* Invalid escape code, let's take it literal then */
1311 *(t++) = '\\';
f3d4cc01 1312 *(t++) = *f;
4fe88d28
LP
1313 break;
1314 }
1315 }
1316
1317finish:
1318 *t = 0;
1319 return r;
1320}
1321
6febfd0d
LP
1322char *cunescape(const char *s) {
1323 return cunescape_length(s, strlen(s));
1324}
4fe88d28
LP
1325
1326char *xescape(const char *s, const char *bad) {
1327 char *r, *t;
1328 const char *f;
1329
1330 /* Escapes all chars in bad, in addition to \ and all special
1331 * chars, in \xFF style escaping. May be reversed with
1332 * cunescape. */
1333
1334 if (!(r = new(char, strlen(s)*4+1)))
1335 return NULL;
1336
1337 for (f = s, t = r; *f; f++) {
1338
b866264a
LP
1339 if ((*f < ' ') || (*f >= 127) ||
1340 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1341 *(t++) = '\\';
1342 *(t++) = 'x';
1343 *(t++) = hexchar(*f >> 4);
1344 *(t++) = hexchar(*f);
1345 } else
1346 *(t++) = *f;
1347 }
1348
1349 *t = 0;
1350
1351 return r;
1352}
1353
ea430986 1354char *bus_path_escape(const char *s) {
ea430986
LP
1355 char *r, *t;
1356 const char *f;
1357
47be870b
LP
1358 assert(s);
1359
ea430986
LP
1360 /* Escapes all chars that D-Bus' object path cannot deal
1361 * with. Can be reverse with bus_path_unescape() */
1362
1363 if (!(r = new(char, strlen(s)*3+1)))
1364 return NULL;
1365
1366 for (f = s, t = r; *f; f++) {
1367
1368 if (!(*f >= 'A' && *f <= 'Z') &&
1369 !(*f >= 'a' && *f <= 'z') &&
1370 !(*f >= '0' && *f <= '9')) {
1371 *(t++) = '_';
1372 *(t++) = hexchar(*f >> 4);
1373 *(t++) = hexchar(*f);
1374 } else
1375 *(t++) = *f;
1376 }
1377
1378 *t = 0;
1379
1380 return r;
1381}
1382
9e2f7c11 1383char *bus_path_unescape(const char *f) {
ea430986 1384 char *r, *t;
ea430986 1385
9e2f7c11 1386 assert(f);
47be870b 1387
9e2f7c11 1388 if (!(r = strdup(f)))
ea430986
LP
1389 return NULL;
1390
9e2f7c11 1391 for (t = r; *f; f++) {
ea430986
LP
1392
1393 if (*f == '_') {
1394 int a, b;
1395
1396 if ((a = unhexchar(f[1])) < 0 ||
1397 (b = unhexchar(f[2])) < 0) {
1398 /* Invalid escape code, let's take it literal then */
1399 *(t++) = '_';
1400 } else {
1401 *(t++) = (char) ((a << 4) | b);
1402 f += 2;
1403 }
1404 } else
1405 *(t++) = *f;
1406 }
1407
1408 *t = 0;
1409
1410 return r;
1411}
1412
4fe88d28
LP
1413char *path_kill_slashes(char *path) {
1414 char *f, *t;
1415 bool slash = false;
1416
1417 /* Removes redundant inner and trailing slashes. Modifies the
1418 * passed string in-place.
1419 *
1420 * ///foo///bar/ becomes /foo/bar
1421 */
1422
1423 for (f = path, t = path; *f; f++) {
1424
1425 if (*f == '/') {
1426 slash = true;
1427 continue;
1428 }
1429
1430 if (slash) {
1431 slash = false;
1432 *(t++) = '/';
1433 }
1434
1435 *(t++) = *f;
1436 }
1437
1438 /* Special rule, if we are talking of the root directory, a
1439 trailing slash is good */
1440
1441 if (t == path && slash)
1442 *(t++) = '/';
1443
1444 *t = 0;
1445 return path;
1446}
1447
1448bool path_startswith(const char *path, const char *prefix) {
1449 assert(path);
1450 assert(prefix);
1451
1452 if ((path[0] == '/') != (prefix[0] == '/'))
1453 return false;
1454
1455 for (;;) {
1456 size_t a, b;
1457
1458 path += strspn(path, "/");
1459 prefix += strspn(prefix, "/");
1460
1461 if (*prefix == 0)
1462 return true;
1463
1464 if (*path == 0)
1465 return false;
1466
1467 a = strcspn(path, "/");
1468 b = strcspn(prefix, "/");
1469
1470 if (a != b)
1471 return false;
1472
1473 if (memcmp(path, prefix, a) != 0)
1474 return false;
1475
1476 path += a;
1477 prefix += b;
1478 }
1479}
1480
15ae422b
LP
1481bool path_equal(const char *a, const char *b) {
1482 assert(a);
1483 assert(b);
1484
1485 if ((a[0] == '/') != (b[0] == '/'))
1486 return false;
1487
1488 for (;;) {
1489 size_t j, k;
1490
1491 a += strspn(a, "/");
1492 b += strspn(b, "/");
1493
1494 if (*a == 0 && *b == 0)
1495 return true;
1496
1497 if (*a == 0 || *b == 0)
1498 return false;
1499
1500 j = strcspn(a, "/");
1501 k = strcspn(b, "/");
1502
1503 if (j != k)
1504 return false;
1505
1506 if (memcmp(a, b, j) != 0)
1507 return false;
1508
1509 a += j;
1510 b += k;
1511 }
1512}
1513
67d51650 1514char *ascii_strlower(char *t) {
4fe88d28
LP
1515 char *p;
1516
67d51650 1517 assert(t);
4fe88d28 1518
67d51650 1519 for (p = t; *p; p++)
4fe88d28
LP
1520 if (*p >= 'A' && *p <= 'Z')
1521 *p = *p - 'A' + 'a';
1522
67d51650 1523 return t;
4fe88d28 1524}
1dccbe19 1525
c85dc17b
LP
1526bool ignore_file(const char *filename) {
1527 assert(filename);
1528
1529 return
1530 filename[0] == '.' ||
6c78be3c 1531 streq(filename, "lost+found") ||
c85dc17b
LP
1532 endswith(filename, "~") ||
1533 endswith(filename, ".rpmnew") ||
1534 endswith(filename, ".rpmsave") ||
1535 endswith(filename, ".rpmorig") ||
1536 endswith(filename, ".dpkg-old") ||
1537 endswith(filename, ".dpkg-new") ||
1538 endswith(filename, ".swp");
1539}
1540
3a0ecb08
LP
1541int fd_nonblock(int fd, bool nonblock) {
1542 int flags;
1543
1544 assert(fd >= 0);
1545
1546 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1547 return -errno;
1548
1549 if (nonblock)
1550 flags |= O_NONBLOCK;
1551 else
1552 flags &= ~O_NONBLOCK;
1553
1554 if (fcntl(fd, F_SETFL, flags) < 0)
1555 return -errno;
1556
1557 return 0;
1558}
1559
1560int fd_cloexec(int fd, bool cloexec) {
1561 int flags;
1562
1563 assert(fd >= 0);
1564
1565 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1566 return -errno;
1567
1568 if (cloexec)
1569 flags |= FD_CLOEXEC;
1570 else
1571 flags &= ~FD_CLOEXEC;
1572
1573 if (fcntl(fd, F_SETFD, flags) < 0)
1574 return -errno;
1575
1576 return 0;
1577}
1578
a0d40ac5
LP
1579int close_all_fds(const int except[], unsigned n_except) {
1580 DIR *d;
1581 struct dirent *de;
1582 int r = 0;
1583
1584 if (!(d = opendir("/proc/self/fd")))
1585 return -errno;
1586
1587 while ((de = readdir(d))) {
a7610064 1588 int fd = -1;
a0d40ac5 1589
a16e1123 1590 if (ignore_file(de->d_name))
a0d40ac5
LP
1591 continue;
1592
1593 if ((r = safe_atoi(de->d_name, &fd)) < 0)
1594 goto finish;
1595
1596 if (fd < 3)
1597 continue;
1598
1599 if (fd == dirfd(d))
1600 continue;
1601
1602 if (except) {
1603 bool found;
1604 unsigned i;
1605
1606 found = false;
1607 for (i = 0; i < n_except; i++)
1608 if (except[i] == fd) {
1609 found = true;
1610 break;
1611 }
1612
1613 if (found)
1614 continue;
1615 }
1616
2f357920
LP
1617 if ((r = close_nointr(fd)) < 0) {
1618 /* Valgrind has its own FD and doesn't want to have it closed */
1619 if (errno != EBADF)
1620 goto finish;
1621 }
a0d40ac5
LP
1622 }
1623
2f357920
LP
1624 r = 0;
1625
a0d40ac5
LP
1626finish:
1627 closedir(d);
1628 return r;
1629}
1630
db12775d
LP
1631bool chars_intersect(const char *a, const char *b) {
1632 const char *p;
1633
1634 /* Returns true if any of the chars in a are in b. */
1635 for (p = a; *p; p++)
1636 if (strchr(b, *p))
1637 return true;
1638
1639 return false;
1640}
1641
8b6c7120
LP
1642char *format_timestamp(char *buf, size_t l, usec_t t) {
1643 struct tm tm;
1644 time_t sec;
1645
1646 assert(buf);
1647 assert(l > 0);
1648
1649 if (t <= 0)
1650 return NULL;
1651
f872ec33 1652 sec = (time_t) (t / USEC_PER_SEC);
8b6c7120
LP
1653
1654 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1655 return NULL;
1656
1657 return buf;
1658}
1659
871d7de4
LP
1660char *format_timespan(char *buf, size_t l, usec_t t) {
1661 static const struct {
1662 const char *suffix;
1663 usec_t usec;
1664 } table[] = {
1665 { "w", USEC_PER_WEEK },
1666 { "d", USEC_PER_DAY },
1667 { "h", USEC_PER_HOUR },
1668 { "min", USEC_PER_MINUTE },
1669 { "s", USEC_PER_SEC },
1670 { "ms", USEC_PER_MSEC },
1671 { "us", 1 },
1672 };
1673
1674 unsigned i;
1675 char *p = buf;
1676
1677 assert(buf);
1678 assert(l > 0);
1679
1680 if (t == (usec_t) -1)
1681 return NULL;
1682
4502d22c
LP
1683 if (t == 0) {
1684 snprintf(p, l, "0");
1685 p[l-1] = 0;
1686 return p;
1687 }
1688
871d7de4
LP
1689 /* The result of this function can be parsed with parse_usec */
1690
1691 for (i = 0; i < ELEMENTSOF(table); i++) {
1692 int k;
1693 size_t n;
1694
1695 if (t < table[i].usec)
1696 continue;
1697
1698 if (l <= 1)
1699 break;
1700
1701 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
1702 n = MIN((size_t) k, l);
1703
1704 l -= n;
1705 p += n;
1706
1707 t %= table[i].usec;
1708 }
1709
1710 *p = 0;
1711
1712 return buf;
1713}
1714
42856c10
LP
1715bool fstype_is_network(const char *fstype) {
1716 static const char * const table[] = {
1717 "cifs",
1718 "smbfs",
1719 "ncpfs",
1720 "nfs",
ca139f94
LP
1721 "nfs4",
1722 "gfs",
1723 "gfs2"
42856c10
LP
1724 };
1725
1726 unsigned i;
1727
1728 for (i = 0; i < ELEMENTSOF(table); i++)
1729 if (streq(table[i], fstype))
1730 return true;
1731
1732 return false;
1733}
1734
601f6a1e
LP
1735int chvt(int vt) {
1736 int fd, r = 0;
1737
1738 if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
1739 return -errno;
1740
1741 if (vt < 0) {
1742 int tiocl[2] = {
1743 TIOCL_GETKMSGREDIRECT,
1744 0
1745 };
1746
1747 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
1748 return -errno;
1749
1750 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
1751 }
1752
1753 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
1754 r = -errno;
1755
a16e1123 1756 close_nointr_nofail(r);
601f6a1e
LP
1757 return r;
1758}
1759
80876c20
LP
1760int read_one_char(FILE *f, char *ret, bool *need_nl) {
1761 struct termios old_termios, new_termios;
1762 char c;
1763 char line[1024];
1764
1765 assert(f);
1766 assert(ret);
1767
1768 if (tcgetattr(fileno(f), &old_termios) >= 0) {
1769 new_termios = old_termios;
1770
1771 new_termios.c_lflag &= ~ICANON;
1772 new_termios.c_cc[VMIN] = 1;
1773 new_termios.c_cc[VTIME] = 0;
1774
1775 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
1776 size_t k;
1777
1778 k = fread(&c, 1, 1, f);
1779
1780 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1781
1782 if (k <= 0)
1783 return -EIO;
1784
1785 if (need_nl)
1786 *need_nl = c != '\n';
1787
1788 *ret = c;
1789 return 0;
1790 }
1791 }
1792
1793 if (!(fgets(line, sizeof(line), f)))
1794 return -EIO;
1795
1796 truncate_nl(line);
1797
1798 if (strlen(line) != 1)
1799 return -EBADMSG;
1800
1801 if (need_nl)
1802 *need_nl = false;
1803
1804 *ret = line[0];
1805 return 0;
1806}
1807
1808int ask(char *ret, const char *replies, const char *text, ...) {
1809 assert(ret);
1810 assert(replies);
1811 assert(text);
1812
1813 for (;;) {
1814 va_list ap;
1815 char c;
1816 int r;
1817 bool need_nl = true;
1818
b1b2dc0c
LP
1819 fputs("\x1B[1m", stdout);
1820
80876c20
LP
1821 va_start(ap, text);
1822 vprintf(text, ap);
1823 va_end(ap);
1824
b1b2dc0c
LP
1825 fputs("\x1B[0m", stdout);
1826
80876c20
LP
1827 fflush(stdout);
1828
1829 if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
1830
1831 if (r == -EBADMSG) {
1832 puts("Bad input, please try again.");
1833 continue;
1834 }
1835
1836 putchar('\n');
1837 return r;
1838 }
1839
1840 if (need_nl)
1841 putchar('\n');
1842
1843 if (strchr(replies, c)) {
1844 *ret = c;
1845 return 0;
1846 }
1847
1848 puts("Read unexpected character, please try again.");
1849 }
1850}
1851
1852int reset_terminal(int fd) {
1853 struct termios termios;
1854 int r = 0;
3fe5e5d4
LP
1855 long arg;
1856
1857 /* Set terminal to some sane defaults */
80876c20
LP
1858
1859 assert(fd >= 0);
1860
3fe5e5d4
LP
1861 /* First, unlock termios */
1862 zero(termios);
1863 ioctl(fd, TIOCSLCKTRMIOS, &termios);
1864
1865 /* Disable exclusive mode, just in case */
1866 ioctl(fd, TIOCNXCL);
1867
1868 /* Enable console unicode mode */
1869 arg = K_UNICODE;
1870 ioctl(fd, KDSKBMODE, &arg);
80876c20
LP
1871
1872 if (tcgetattr(fd, &termios) < 0) {
1873 r = -errno;
1874 goto finish;
1875 }
1876
aaf694ca
LP
1877 /* We only reset the stuff that matters to the software. How
1878 * hardware is set up we don't touch assuming that somebody
1879 * else will do that for us */
1880
1881 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
1882 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
1883 termios.c_oflag |= ONLCR;
1884 termios.c_cflag |= CREAD;
1885 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
1886
1887 termios.c_cc[VINTR] = 03; /* ^C */
1888 termios.c_cc[VQUIT] = 034; /* ^\ */
1889 termios.c_cc[VERASE] = 0177;
1890 termios.c_cc[VKILL] = 025; /* ^X */
1891 termios.c_cc[VEOF] = 04; /* ^D */
1892 termios.c_cc[VSTART] = 021; /* ^Q */
1893 termios.c_cc[VSTOP] = 023; /* ^S */
1894 termios.c_cc[VSUSP] = 032; /* ^Z */
1895 termios.c_cc[VLNEXT] = 026; /* ^V */
1896 termios.c_cc[VWERASE] = 027; /* ^W */
1897 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
1898 termios.c_cc[VEOL] = 0;
1899 termios.c_cc[VEOL2] = 0;
80876c20
LP
1900
1901 termios.c_cc[VTIME] = 0;
1902 termios.c_cc[VMIN] = 1;
1903
1904 if (tcsetattr(fd, TCSANOW, &termios) < 0)
1905 r = -errno;
1906
1907finish:
1908 /* Just in case, flush all crap out */
1909 tcflush(fd, TCIOFLUSH);
1910
1911 return r;
1912}
1913
1914int open_terminal(const char *name, int mode) {
1915 int fd, r;
1916
1917 if ((fd = open(name, mode)) < 0)
1918 return -errno;
1919
1920 if ((r = isatty(fd)) < 0) {
1921 close_nointr_nofail(fd);
1922 return -errno;
1923 }
1924
1925 if (!r) {
1926 close_nointr_nofail(fd);
1927 return -ENOTTY;
1928 }
1929
1930 return fd;
1931}
1932
1933int flush_fd(int fd) {
1934 struct pollfd pollfd;
1935
1936 zero(pollfd);
1937 pollfd.fd = fd;
1938 pollfd.events = POLLIN;
1939
1940 for (;;) {
1941 char buf[1024];
1942 ssize_t l;
1943 int r;
1944
1945 if ((r = poll(&pollfd, 1, 0)) < 0) {
1946
1947 if (errno == EINTR)
1948 continue;
1949
1950 return -errno;
1951 }
1952
1953 if (r == 0)
1954 return 0;
1955
1956 if ((l = read(fd, buf, sizeof(buf))) < 0) {
1957
1958 if (errno == EINTR)
1959 continue;
1960
1961 if (errno == EAGAIN)
1962 return 0;
1963
1964 return -errno;
1965 }
1966
1967 if (l <= 0)
1968 return 0;
1969 }
1970}
1971
21de3988 1972int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm) {
bab45044 1973 int fd = -1, notify = -1, r, wd = -1;
80876c20
LP
1974
1975 assert(name);
1976
1977 /* We use inotify to be notified when the tty is closed. We
1978 * create the watch before checking if we can actually acquire
1979 * it, so that we don't lose any event.
1980 *
1981 * Note: strictly speaking this actually watches for the
1982 * device being closed, it does *not* really watch whether a
1983 * tty loses its controlling process. However, unless some
1984 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
1985 * its tty otherwise this will not become a problem. As long
1986 * as the administrator makes sure not configure any service
1987 * on the same tty as an untrusted user this should not be a
1988 * problem. (Which he probably should not do anyway.) */
1989
1990 if (!fail && !force) {
1991 if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
1992 r = -errno;
1993 goto fail;
1994 }
1995
1996 if ((wd = inotify_add_watch(notify, name, IN_CLOSE)) < 0) {
1997 r = -errno;
1998 goto fail;
1999 }
2000 }
2001
2002 for (;;) {
e3d1855b
LP
2003 if (notify >= 0)
2004 if ((r = flush_fd(notify)) < 0)
2005 goto fail;
80876c20
LP
2006
2007 /* We pass here O_NOCTTY only so that we can check the return
2008 * value TIOCSCTTY and have a reliable way to figure out if we
2009 * successfully became the controlling process of the tty */
2010 if ((fd = open_terminal(name, O_RDWR|O_NOCTTY)) < 0)
2011 return -errno;
2012
2013 /* First, try to get the tty */
21de3988
LP
2014 r = ioctl(fd, TIOCSCTTY, force);
2015
2016 /* Sometimes it makes sense to ignore TIOCSCTTY
2017 * returning EPERM, i.e. when very likely we already
2018 * are have this controlling terminal. */
2019 if (r < 0 && errno == EPERM && ignore_tiocstty_eperm)
2020 r = 0;
2021
2022 if (r < 0 && (force || fail || errno != EPERM)) {
80876c20
LP
2023 r = -errno;
2024 goto fail;
2025 }
2026
2027 if (r >= 0)
2028 break;
2029
2030 assert(!fail);
2031 assert(!force);
2032 assert(notify >= 0);
2033
2034 for (;;) {
2035 struct inotify_event e;
2036 ssize_t l;
2037
2038 if ((l = read(notify, &e, sizeof(e))) != sizeof(e)) {
2039
2040 if (l < 0) {
2041
2042 if (errno == EINTR)
2043 continue;
2044
2045 r = -errno;
2046 } else
2047 r = -EIO;
2048
2049 goto fail;
2050 }
2051
2052 if (e.wd != wd || !(e.mask & IN_CLOSE)) {
7bc0351d 2053 r = -EIO;
80876c20
LP
2054 goto fail;
2055 }
2056
2057 break;
2058 }
2059
2060 /* We close the tty fd here since if the old session
2061 * ended our handle will be dead. It's important that
2062 * we do this after sleeping, so that we don't enter
2063 * an endless loop. */
2064 close_nointr_nofail(fd);
2065 }
2066
2067 if (notify >= 0)
a16e1123 2068 close_nointr_nofail(notify);
80876c20
LP
2069
2070 if ((r = reset_terminal(fd)) < 0)
2071 log_warning("Failed to reset terminal: %s", strerror(-r));
2072
2073 return fd;
2074
2075fail:
2076 if (fd >= 0)
a16e1123 2077 close_nointr_nofail(fd);
80876c20
LP
2078
2079 if (notify >= 0)
a16e1123 2080 close_nointr_nofail(notify);
80876c20
LP
2081
2082 return r;
2083}
2084
2085int release_terminal(void) {
2086 int r = 0, fd;
57cd2192 2087 struct sigaction sa_old, sa_new;
80876c20 2088
57cd2192 2089 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
80876c20
LP
2090 return -errno;
2091
57cd2192
LP
2092 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
2093 * by our own TIOCNOTTY */
2094
2095 zero(sa_new);
2096 sa_new.sa_handler = SIG_IGN;
2097 sa_new.sa_flags = SA_RESTART;
2098 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
2099
80876c20
LP
2100 if (ioctl(fd, TIOCNOTTY) < 0)
2101 r = -errno;
2102
57cd2192
LP
2103 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
2104
80876c20
LP
2105 close_nointr_nofail(fd);
2106 return r;
2107}
2108
9a34ec5f
LP
2109int sigaction_many(const struct sigaction *sa, ...) {
2110 va_list ap;
2111 int r = 0, sig;
2112
2113 va_start(ap, sa);
2114 while ((sig = va_arg(ap, int)) > 0)
2115 if (sigaction(sig, sa, NULL) < 0)
2116 r = -errno;
2117 va_end(ap);
2118
2119 return r;
2120}
2121
2122int ignore_signals(int sig, ...) {
a337c6fc 2123 struct sigaction sa;
9a34ec5f
LP
2124 va_list ap;
2125 int r = 0;
a337c6fc
LP
2126
2127 zero(sa);
2128 sa.sa_handler = SIG_IGN;
2129 sa.sa_flags = SA_RESTART;
2130
9a34ec5f
LP
2131 if (sigaction(sig, &sa, NULL) < 0)
2132 r = -errno;
2133
2134 va_start(ap, sig);
2135 while ((sig = va_arg(ap, int)) > 0)
2136 if (sigaction(sig, &sa, NULL) < 0)
2137 r = -errno;
2138 va_end(ap);
2139
2140 return r;
2141}
2142
2143int default_signals(int sig, ...) {
2144 struct sigaction sa;
2145 va_list ap;
2146 int r = 0;
2147
2148 zero(sa);
2149 sa.sa_handler = SIG_DFL;
2150 sa.sa_flags = SA_RESTART;
2151
2152 if (sigaction(sig, &sa, NULL) < 0)
2153 r = -errno;
2154
2155 va_start(ap, sig);
2156 while ((sig = va_arg(ap, int)) > 0)
2157 if (sigaction(sig, &sa, NULL) < 0)
2158 r = -errno;
2159 va_end(ap);
2160
2161 return r;
a337c6fc
LP
2162}
2163
8d567588
LP
2164int close_pipe(int p[]) {
2165 int a = 0, b = 0;
2166
2167 assert(p);
2168
2169 if (p[0] >= 0) {
2170 a = close_nointr(p[0]);
2171 p[0] = -1;
2172 }
2173
2174 if (p[1] >= 0) {
2175 b = close_nointr(p[1]);
2176 p[1] = -1;
2177 }
2178
2179 return a < 0 ? a : b;
2180}
2181
eb22ac37 2182ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
8d567588
LP
2183 uint8_t *p;
2184 ssize_t n = 0;
2185
2186 assert(fd >= 0);
2187 assert(buf);
2188
2189 p = buf;
2190
2191 while (nbytes > 0) {
2192 ssize_t k;
2193
2194 if ((k = read(fd, p, nbytes)) <= 0) {
2195
eb22ac37 2196 if (k < 0 && errno == EINTR)
8d567588
LP
2197 continue;
2198
eb22ac37 2199 if (k < 0 && errno == EAGAIN && do_poll) {
8d567588
LP
2200 struct pollfd pollfd;
2201
2202 zero(pollfd);
2203 pollfd.fd = fd;
2204 pollfd.events = POLLIN;
2205
2206 if (poll(&pollfd, 1, -1) < 0) {
2207 if (errno == EINTR)
2208 continue;
2209
2210 return n > 0 ? n : -errno;
2211 }
2212
2213 if (pollfd.revents != POLLIN)
2214 return n > 0 ? n : -EIO;
2215
2216 continue;
2217 }
2218
2219 return n > 0 ? n : (k < 0 ? -errno : 0);
2220 }
2221
2222 p += k;
2223 nbytes -= k;
2224 n += k;
2225 }
2226
2227 return n;
2228}
2229
eb22ac37
LP
2230ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2231 const uint8_t *p;
2232 ssize_t n = 0;
2233
2234 assert(fd >= 0);
2235 assert(buf);
2236
2237 p = buf;
2238
2239 while (nbytes > 0) {
2240 ssize_t k;
2241
2242 if ((k = write(fd, p, nbytes)) <= 0) {
2243
2244 if (k < 0 && errno == EINTR)
2245 continue;
2246
2247 if (k < 0 && errno == EAGAIN && do_poll) {
2248 struct pollfd pollfd;
2249
2250 zero(pollfd);
2251 pollfd.fd = fd;
2252 pollfd.events = POLLOUT;
2253
2254 if (poll(&pollfd, 1, -1) < 0) {
2255 if (errno == EINTR)
2256 continue;
2257
2258 return n > 0 ? n : -errno;
2259 }
2260
2261 if (pollfd.revents != POLLOUT)
2262 return n > 0 ? n : -EIO;
2263
2264 continue;
2265 }
2266
2267 return n > 0 ? n : (k < 0 ? -errno : 0);
2268 }
2269
2270 p += k;
2271 nbytes -= k;
2272 n += k;
2273 }
2274
2275 return n;
2276}
2277
8d567588
LP
2278int path_is_mount_point(const char *t) {
2279 struct stat a, b;
35d2e7ec
LP
2280 char *parent;
2281 int r;
8d567588
LP
2282
2283 if (lstat(t, &a) < 0) {
8d567588
LP
2284 if (errno == ENOENT)
2285 return 0;
2286
2287 return -errno;
2288 }
2289
35d2e7ec
LP
2290 if ((r = parent_of_path(t, &parent)) < 0)
2291 return r;
8d567588 2292
35d2e7ec
LP
2293 r = lstat(parent, &b);
2294 free(parent);
8d567588 2295
35d2e7ec
LP
2296 if (r < 0)
2297 return -errno;
8d567588
LP
2298
2299 return a.st_dev != b.st_dev;
2300}
2301
24a6e4a4
LP
2302int parse_usec(const char *t, usec_t *usec) {
2303 static const struct {
2304 const char *suffix;
2305 usec_t usec;
2306 } table[] = {
2307 { "sec", USEC_PER_SEC },
2308 { "s", USEC_PER_SEC },
2309 { "min", USEC_PER_MINUTE },
2310 { "hr", USEC_PER_HOUR },
2311 { "h", USEC_PER_HOUR },
2312 { "d", USEC_PER_DAY },
2313 { "w", USEC_PER_WEEK },
2314 { "msec", USEC_PER_MSEC },
2315 { "ms", USEC_PER_MSEC },
2316 { "m", USEC_PER_MINUTE },
2317 { "usec", 1ULL },
2318 { "us", 1ULL },
2319 { "", USEC_PER_SEC },
2320 };
2321
2322 const char *p;
2323 usec_t r = 0;
2324
2325 assert(t);
2326 assert(usec);
2327
2328 p = t;
2329 do {
2330 long long l;
2331 char *e;
2332 unsigned i;
2333
2334 errno = 0;
2335 l = strtoll(p, &e, 10);
2336
2337 if (errno != 0)
2338 return -errno;
2339
2340 if (l < 0)
2341 return -ERANGE;
2342
2343 if (e == p)
2344 return -EINVAL;
2345
2346 e += strspn(e, WHITESPACE);
2347
2348 for (i = 0; i < ELEMENTSOF(table); i++)
2349 if (startswith(e, table[i].suffix)) {
2350 r += (usec_t) l * table[i].usec;
2351 p = e + strlen(table[i].suffix);
2352 break;
2353 }
2354
2355 if (i >= ELEMENTSOF(table))
2356 return -EINVAL;
2357
2358 } while (*p != 0);
2359
2360 *usec = r;
2361
2362 return 0;
2363}
2364
843d2643
LP
2365int make_stdio(int fd) {
2366 int r, s, t;
2367
2368 assert(fd >= 0);
2369
2370 r = dup2(fd, STDIN_FILENO);
2371 s = dup2(fd, STDOUT_FILENO);
2372 t = dup2(fd, STDERR_FILENO);
2373
2374 if (fd >= 3)
2375 close_nointr_nofail(fd);
2376
2377 if (r < 0 || s < 0 || t < 0)
2378 return -errno;
2379
2380 return 0;
2381}
2382
cb8a8f78
LP
2383bool is_clean_exit(int code, int status) {
2384
2385 if (code == CLD_EXITED)
2386 return status == 0;
2387
2388 /* If a daemon does not implement handlers for some of the
2389 * signals that's not considered an unclean shutdown */
2390 if (code == CLD_KILLED)
2391 return
2392 status == SIGHUP ||
2393 status == SIGINT ||
2394 status == SIGTERM ||
2395 status == SIGPIPE;
2396
2397 return false;
2398}
2399
8407a5d0
LP
2400bool is_device_path(const char *path) {
2401
2402 /* Returns true on paths that refer to a device, either in
2403 * sysfs or in /dev */
2404
2405 return
2406 path_startswith(path, "/dev/") ||
2407 path_startswith(path, "/sys/");
2408}
2409
01f78473
LP
2410int dir_is_empty(const char *path) {
2411 DIR *d;
2412 int r;
2413 struct dirent buf, *de;
2414
2415 if (!(d = opendir(path)))
2416 return -errno;
2417
2418 for (;;) {
2419 if ((r = readdir_r(d, &buf, &de)) > 0) {
2420 r = -r;
2421 break;
2422 }
2423
2424 if (!de) {
2425 r = 1;
2426 break;
2427 }
2428
2429 if (!ignore_file(de->d_name)) {
2430 r = 0;
2431 break;
2432 }
2433 }
2434
2435 closedir(d);
2436 return r;
2437}
2438
d3782d60
LP
2439unsigned long long random_ull(void) {
2440 int fd;
2441 uint64_t ull;
2442 ssize_t r;
2443
2444 if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0)
2445 goto fallback;
2446
eb22ac37 2447 r = loop_read(fd, &ull, sizeof(ull), true);
d3782d60
LP
2448 close_nointr_nofail(fd);
2449
2450 if (r != sizeof(ull))
2451 goto fallback;
2452
2453 return ull;
2454
2455fallback:
2456 return random() * RAND_MAX + random();
2457}
2458
5b6319dc
LP
2459void rename_process(const char name[8]) {
2460 assert(name);
2461
2462 prctl(PR_SET_NAME, name);
2463
2464 /* This is a like a poor man's setproctitle(). The string
2465 * passed should fit in 7 chars (i.e. the length of
2466 * "systemd") */
2467
2468 if (program_invocation_name)
2469 strncpy(program_invocation_name, name, strlen(program_invocation_name));
2470}
2471
7d793605
LP
2472void sigset_add_many(sigset_t *ss, ...) {
2473 va_list ap;
2474 int sig;
2475
2476 assert(ss);
2477
2478 va_start(ap, ss);
2479 while ((sig = va_arg(ap, int)) > 0)
2480 assert_se(sigaddset(ss, sig) == 0);
2481 va_end(ap);
2482}
2483
ef2f1067
LP
2484char* gethostname_malloc(void) {
2485 struct utsname u;
2486
2487 assert_se(uname(&u) >= 0);
2488
2489 if (u.nodename[0])
2490 return strdup(u.nodename);
2491
2492 return strdup(u.sysname);
2493}
2494
2495char* getlogname_malloc(void) {
2496 uid_t uid;
2497 long bufsize;
2498 char *buf, *name;
2499 struct passwd pwbuf, *pw = NULL;
2500 struct stat st;
2501
2502 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2503 uid = st.st_uid;
2504 else
2505 uid = getuid();
2506
2507 /* Shortcut things to avoid NSS lookups */
2508 if (uid == 0)
2509 return strdup("root");
2510
2511 if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) <= 0)
2512 bufsize = 4096;
2513
2514 if (!(buf = malloc(bufsize)))
2515 return NULL;
2516
2517 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
2518 name = strdup(pw->pw_name);
2519 free(buf);
2520 return name;
2521 }
2522
2523 free(buf);
2524
2525 if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
2526 return NULL;
2527
2528 return name;
2529}
2530
8c6db833
LP
2531int getttyname_malloc(char **r) {
2532 char path[PATH_MAX], *p, *c;
2533
2534 assert(r);
ef2f1067
LP
2535
2536 if (ttyname_r(STDIN_FILENO, path, sizeof(path)) < 0)
8c6db833 2537 return -errno;
ef2f1067
LP
2538
2539 char_array_0(path);
2540
2541 p = path;
2542 if (startswith(path, "/dev/"))
2543 p += 5;
2544
8c6db833
LP
2545 if (!(c = strdup(p)))
2546 return -ENOMEM;
2547
2548 *r = c;
2549 return 0;
2550}
2551
2552static int rm_rf_children(int fd, bool only_dirs) {
2553 DIR *d;
2554 int ret = 0;
2555
2556 assert(fd >= 0);
2557
2558 /* This returns the first error we run into, but nevertheless
2559 * tries to go on */
2560
2561 if (!(d = fdopendir(fd))) {
2562 close_nointr_nofail(fd);
4c633005
LP
2563
2564 return errno == ENOENT ? 0 : -errno;
8c6db833
LP
2565 }
2566
2567 for (;;) {
2568 struct dirent buf, *de;
2569 bool is_dir;
2570 int r;
2571
2572 if ((r = readdir_r(d, &buf, &de)) != 0) {
2573 if (ret == 0)
2574 ret = -r;
2575 break;
2576 }
2577
2578 if (!de)
2579 break;
2580
2581 if (streq(de->d_name, ".") || streq(de->d_name, ".."))
2582 continue;
2583
2584 if (de->d_type == DT_UNKNOWN) {
2585 struct stat st;
2586
2587 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
4c633005 2588 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2589 ret = -errno;
2590 continue;
2591 }
2592
2593 is_dir = S_ISDIR(st.st_mode);
2594 } else
2595 is_dir = de->d_type == DT_DIR;
2596
2597 if (is_dir) {
2598 int subdir_fd;
2599
2600 if ((subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
4c633005 2601 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2602 ret = -errno;
2603 continue;
2604 }
2605
2606 if ((r = rm_rf_children(subdir_fd, only_dirs)) < 0) {
2607 if (ret == 0)
2608 ret = r;
2609 }
2610
2611 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
4c633005 2612 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2613 ret = -errno;
2614 }
2615 } else if (!only_dirs) {
2616
2617 if (unlinkat(fd, de->d_name, 0) < 0) {
4c633005 2618 if (ret == 0 && errno != ENOENT)
8c6db833
LP
2619 ret = -errno;
2620 }
2621 }
2622 }
2623
2624 closedir(d);
2625
2626 return ret;
2627}
2628
2629int rm_rf(const char *path, bool only_dirs, bool delete_root) {
2630 int fd;
2631 int r;
2632
2633 assert(path);
2634
2635 if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
2636
2637 if (errno != ENOTDIR)
2638 return -errno;
2639
2640 if (delete_root && !only_dirs)
2641 if (unlink(path) < 0)
2642 return -errno;
2643
2644 return 0;
2645 }
2646
2647 r = rm_rf_children(fd, only_dirs);
2648
2649 if (delete_root)
2650 if (rmdir(path) < 0) {
2651 if (r == 0)
2652 r = -errno;
2653 }
2654
2655 return r;
2656}
2657
2658int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2659 assert(path);
2660
2661 /* Under the assumption that we are running privileged we
2662 * first change the access mode and only then hand out
2663 * ownership to avoid a window where access is too open. */
2664
2665 if (chmod(path, mode) < 0)
2666 return -errno;
2667
2668 if (chown(path, uid, gid) < 0)
2669 return -errno;
2670
2671 return 0;
ef2f1067
LP
2672}
2673
82c121a4
LP
2674cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2675 cpu_set_t *r;
2676 unsigned n = 1024;
2677
2678 /* Allocates the cpuset in the right size */
2679
2680 for (;;) {
2681 if (!(r = CPU_ALLOC(n)))
2682 return NULL;
2683
2684 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2685 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2686
2687 if (ncpus)
2688 *ncpus = n;
2689
2690 return r;
2691 }
2692
2693 CPU_FREE(r);
2694
2695 if (errno != EINVAL)
2696 return NULL;
2697
2698 n *= 2;
2699 }
2700}
2701
9e58ff9c
LP
2702void status_vprintf(const char *format, va_list ap) {
2703 char *s = NULL;
2704 int fd = -1;
2705
2706 assert(format);
2707
2708 /* This independent of logging, as status messages are
2709 * optional and go exclusively to the console. */
2710
2711 if (vasprintf(&s, format, ap) < 0)
2712 goto finish;
2713
2714 if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
2715 goto finish;
2716
2717 write(fd, s, strlen(s));
2718
2719finish:
2720 free(s);
2721
2722 if (fd >= 0)
2723 close_nointr_nofail(fd);
2724}
2725
c846ff47
LP
2726void status_printf(const char *format, ...) {
2727 va_list ap;
2728
2729 assert(format);
2730
2731 va_start(ap, format);
2732 status_vprintf(format, ap);
2733 va_end(ap);
2734}
2735
2736void status_welcome(void) {
2737
2738#if defined(TARGET_FEDORA)
2739 char *r;
2740
2741 if (read_one_line_file("/etc/system-release", &r) < 0)
2742 return;
2743
2744 truncate_nl(r);
2745
2746 /* This tries to mimic the color magic the old Red Hat sysinit
2747 * script did. */
2748
2749 if (startswith(r, "Red Hat"))
2e54424d 2750 status_printf("Welcome to \x1B[0;31m%s\x1B[0m!\n", r); /* Red for RHEL */
c846ff47 2751 else if (startswith(r, "Fedora"))
2e54424d 2752 status_printf("Welcome to \x1B[0;34m%s\x1B[0m!\n", r); /* Blue for Fedora */
c846ff47 2753 else
2e54424d 2754 status_printf("Welcome to %s!\n", r);
c846ff47
LP
2755
2756 free(r);
2757
2758#elif defined(TARGET_SUSE)
2759 char *r;
2760
2761 if (read_one_line_file("/etc/SuSE-release", &r) < 0)
2762 return;
2763
2764 truncate_nl(r);
2765
2e54424d 2766 status_printf("Welcome to \x1B[0;32m%s\x1B[0m!\n", r); /* Green for SUSE */
c846ff47
LP
2767 free(r);
2768#else
2769#warning "You probably should add a welcome text logic here."
2770#endif
2771}
2772
fab56fc5
LP
2773char *replace_env(const char *format, char **env) {
2774 enum {
2775 WORD,
c24eb49e 2776 CURLY,
fab56fc5
LP
2777 VARIABLE
2778 } state = WORD;
2779
2780 const char *e, *word = format;
2781 char *r = NULL, *k;
2782
2783 assert(format);
2784
2785 for (e = format; *e; e ++) {
2786
2787 switch (state) {
2788
2789 case WORD:
2790 if (*e == '$')
c24eb49e 2791 state = CURLY;
fab56fc5
LP
2792 break;
2793
c24eb49e
LP
2794 case CURLY:
2795 if (*e == '{') {
fab56fc5
LP
2796 if (!(k = strnappend(r, word, e-word-1)))
2797 goto fail;
2798
2799 free(r);
2800 r = k;
2801
2802 word = e-1;
2803 state = VARIABLE;
2804
2805 } else if (*e == '$') {
2806 if (!(k = strnappend(r, word, e-word)))
2807 goto fail;
2808
2809 free(r);
2810 r = k;
2811
2812 word = e+1;
2813 state = WORD;
2814 } else
2815 state = WORD;
2816 break;
2817
2818 case VARIABLE:
c24eb49e 2819 if (*e == '}') {
b95cf362 2820 const char *t;
fab56fc5 2821
b95cf362
LP
2822 if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
2823 t = "";
fab56fc5 2824
b95cf362
LP
2825 if (!(k = strappend(r, t)))
2826 goto fail;
fab56fc5 2827
b95cf362
LP
2828 free(r);
2829 r = k;
fab56fc5 2830
b95cf362 2831 word = e+1;
fab56fc5
LP
2832 state = WORD;
2833 }
2834 break;
2835 }
2836 }
2837
2838 if (!(k = strnappend(r, word, e-word)))
2839 goto fail;
2840
2841 free(r);
2842 return k;
2843
2844fail:
2845 free(r);
2846 return NULL;
2847}
2848
2849char **replace_env_argv(char **argv, char **env) {
2850 char **r, **i;
c24eb49e
LP
2851 unsigned k = 0, l = 0;
2852
2853 l = strv_length(argv);
fab56fc5 2854
c24eb49e 2855 if (!(r = new(char*, l+1)))
fab56fc5
LP
2856 return NULL;
2857
2858 STRV_FOREACH(i, argv) {
c24eb49e
LP
2859
2860 /* If $FOO appears as single word, replace it by the split up variable */
b95cf362
LP
2861 if ((*i)[0] == '$' && (*i)[1] != '{') {
2862 char *e;
2863 char **w, **m;
2864 unsigned q;
c24eb49e 2865
b95cf362 2866 if ((e = strv_env_get(env, *i+1))) {
c24eb49e
LP
2867
2868 if (!(m = strv_split_quoted(e))) {
2869 r[k] = NULL;
2870 strv_free(r);
2871 return NULL;
2872 }
b95cf362
LP
2873 } else
2874 m = NULL;
c24eb49e 2875
b95cf362
LP
2876 q = strv_length(m);
2877 l = l + q - 1;
c24eb49e 2878
b95cf362
LP
2879 if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
2880 r[k] = NULL;
2881 strv_free(r);
2882 strv_free(m);
2883 return NULL;
2884 }
c24eb49e 2885
b95cf362
LP
2886 r = w;
2887 if (m) {
c24eb49e
LP
2888 memcpy(r + k, m, q * sizeof(char*));
2889 free(m);
c24eb49e 2890 }
b95cf362
LP
2891
2892 k += q;
2893 continue;
c24eb49e
LP
2894 }
2895
2896 /* If ${FOO} appears as part of a word, replace it by the variable as-is */
fab56fc5
LP
2897 if (!(r[k++] = replace_env(*i, env))) {
2898 strv_free(r);
2899 return NULL;
2900 }
2901 }
2902
2903 r[k] = NULL;
2904 return r;
2905}
2906
fa776d8e
LP
2907int columns(void) {
2908 static __thread int parsed_columns = 0;
2909 const char *e;
2910
2911 if (parsed_columns > 0)
2912 return parsed_columns;
2913
2914 if ((e = getenv("COLUMNS")))
2915 parsed_columns = atoi(e);
2916
2917 if (parsed_columns <= 0) {
2918 struct winsize ws;
2919 zero(ws);
2920
2921 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
2922 parsed_columns = ws.ws_col;
2923 }
2924
2925 if (parsed_columns <= 0)
2926 parsed_columns = 80;
2927
2928 return parsed_columns;
2929}
2930
b4f10a5e
LP
2931int running_in_chroot(void) {
2932 struct stat a, b;
2933
2934 zero(a);
2935 zero(b);
2936
2937 /* Only works as root */
2938
2939 if (stat("/proc/1/root", &a) < 0)
2940 return -errno;
2941
2942 if (stat("/", &b) < 0)
2943 return -errno;
2944
2945 return
2946 a.st_dev != b.st_dev ||
2947 a.st_ino != b.st_ino;
2948}
2949
8fe914ec
LP
2950char *ellipsize(const char *s, unsigned length, unsigned percent) {
2951 size_t l, x;
2952 char *r;
2953
2954 assert(s);
2955 assert(percent <= 100);
2956 assert(length >= 3);
2957
2958 l = strlen(s);
2959
2960 if (l <= 3 || l <= length)
2961 return strdup(s);
2962
2963 if (!(r = new0(char, length+1)))
2964 return r;
2965
2966 x = (length * percent) / 100;
2967
2968 if (x > length - 3)
2969 x = length - 3;
2970
2971 memcpy(r, s, x);
2972 r[x] = '.';
2973 r[x+1] = '.';
2974 r[x+2] = '.';
2975 memcpy(r + x + 3,
2976 s + l - (length - x - 3),
2977 length - x - 3);
2978
2979 return r;
2980}
2981
1dccbe19
LP
2982static const char *const ioprio_class_table[] = {
2983 [IOPRIO_CLASS_NONE] = "none",
2984 [IOPRIO_CLASS_RT] = "realtime",
2985 [IOPRIO_CLASS_BE] = "best-effort",
2986 [IOPRIO_CLASS_IDLE] = "idle"
2987};
2988
2989DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
2990
2991static const char *const sigchld_code_table[] = {
2992 [CLD_EXITED] = "exited",
2993 [CLD_KILLED] = "killed",
2994 [CLD_DUMPED] = "dumped",
2995 [CLD_TRAPPED] = "trapped",
2996 [CLD_STOPPED] = "stopped",
2997 [CLD_CONTINUED] = "continued",
2998};
2999
3000DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
3001
3002static const char *const log_facility_table[LOG_NFACILITIES] = {
3003 [LOG_FAC(LOG_KERN)] = "kern",
3004 [LOG_FAC(LOG_USER)] = "user",
3005 [LOG_FAC(LOG_MAIL)] = "mail",
3006 [LOG_FAC(LOG_DAEMON)] = "daemon",
3007 [LOG_FAC(LOG_AUTH)] = "auth",
3008 [LOG_FAC(LOG_SYSLOG)] = "syslog",
3009 [LOG_FAC(LOG_LPR)] = "lpr",
3010 [LOG_FAC(LOG_NEWS)] = "news",
3011 [LOG_FAC(LOG_UUCP)] = "uucp",
3012 [LOG_FAC(LOG_CRON)] = "cron",
3013 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
3014 [LOG_FAC(LOG_FTP)] = "ftp",
3015 [LOG_FAC(LOG_LOCAL0)] = "local0",
3016 [LOG_FAC(LOG_LOCAL1)] = "local1",
3017 [LOG_FAC(LOG_LOCAL2)] = "local2",
3018 [LOG_FAC(LOG_LOCAL3)] = "local3",
3019 [LOG_FAC(LOG_LOCAL4)] = "local4",
3020 [LOG_FAC(LOG_LOCAL5)] = "local5",
3021 [LOG_FAC(LOG_LOCAL6)] = "local6",
3022 [LOG_FAC(LOG_LOCAL7)] = "local7"
3023};
3024
3025DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
3026
3027static const char *const log_level_table[] = {
3028 [LOG_EMERG] = "emerg",
3029 [LOG_ALERT] = "alert",
3030 [LOG_CRIT] = "crit",
3031 [LOG_ERR] = "err",
3032 [LOG_WARNING] = "warning",
3033 [LOG_NOTICE] = "notice",
3034 [LOG_INFO] = "info",
3035 [LOG_DEBUG] = "debug"
3036};
3037
3038DEFINE_STRING_TABLE_LOOKUP(log_level, int);
3039
3040static const char* const sched_policy_table[] = {
3041 [SCHED_OTHER] = "other",
3042 [SCHED_BATCH] = "batch",
3043 [SCHED_IDLE] = "idle",
3044 [SCHED_FIFO] = "fifo",
3045 [SCHED_RR] = "rr"
3046};
3047
3048DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
3049
3050static const char* const rlimit_table[] = {
3051 [RLIMIT_CPU] = "LimitCPU",
3052 [RLIMIT_FSIZE] = "LimitFSIZE",
3053 [RLIMIT_DATA] = "LimitDATA",
3054 [RLIMIT_STACK] = "LimitSTACK",
3055 [RLIMIT_CORE] = "LimitCORE",
3056 [RLIMIT_RSS] = "LimitRSS",
3057 [RLIMIT_NOFILE] = "LimitNOFILE",
3058 [RLIMIT_AS] = "LimitAS",
3059 [RLIMIT_NPROC] = "LimitNPROC",
3060 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
3061 [RLIMIT_LOCKS] = "LimitLOCKS",
3062 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
3063 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
3064 [RLIMIT_NICE] = "LimitNICE",
3065 [RLIMIT_RTPRIO] = "LimitRTPRIO",
3066 [RLIMIT_RTTIME] = "LimitRTTIME"
3067};
3068
3069DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
4fd5948e
LP
3070
3071static const char* const ip_tos_table[] = {
3072 [IPTOS_LOWDELAY] = "low-delay",
3073 [IPTOS_THROUGHPUT] = "throughput",
3074 [IPTOS_RELIABILITY] = "reliability",
3075 [IPTOS_LOWCOST] = "low-cost",
3076};
3077
3078DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
2e22afe9
LP
3079
3080static const char *const signal_table[] = {
3081 [SIGHUP] = "HUP",
3082 [SIGINT] = "INT",
3083 [SIGQUIT] = "QUIT",
3084 [SIGILL] = "ILL",
3085 [SIGTRAP] = "TRAP",
3086 [SIGABRT] = "ABRT",
3087 [SIGBUS] = "BUS",
3088 [SIGFPE] = "FPE",
3089 [SIGKILL] = "KILL",
3090 [SIGUSR1] = "USR1",
3091 [SIGSEGV] = "SEGV",
3092 [SIGUSR2] = "USR2",
3093 [SIGPIPE] = "PIPE",
3094 [SIGALRM] = "ALRM",
3095 [SIGTERM] = "TERM",
3096 [SIGSTKFLT] = "STKFLT",
3097 [SIGCHLD] = "CHLD",
3098 [SIGCONT] = "CONT",
3099 [SIGSTOP] = "STOP",
3100 [SIGTSTP] = "TSTP",
3101 [SIGTTIN] = "TTIN",
3102 [SIGTTOU] = "TTOU",
3103 [SIGURG] = "URG",
3104 [SIGXCPU] = "XCPU",
3105 [SIGXFSZ] = "XFSZ",
3106 [SIGVTALRM] = "VTALRM",
3107 [SIGPROF] = "PROF",
3108 [SIGWINCH] = "WINCH",
3109 [SIGIO] = "IO",
3110 [SIGPWR] = "PWR",
3111 [SIGSYS] = "SYS"
3112};
3113
3114DEFINE_STRING_TABLE_LOOKUP(signal, int);