]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/util.c
notify: add systemd-notify command line tool
[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>
60918275
LP
47
48#include "macro.h"
49#include "util.h"
1dccbe19
LP
50#include "ioprio.h"
51#include "missing.h"
a9f5d454 52#include "log.h"
65d2ebdc 53#include "strv.h"
60918275 54
e05797fb
LP
55bool streq_ptr(const char *a, const char *b) {
56
57 /* Like streq(), but tries to make sense of NULL pointers */
58
59 if (a && b)
60 return streq(a, b);
61
62 if (!a && !b)
63 return true;
64
65 return false;
66}
67
47be870b 68usec_t now(clockid_t clock_id) {
60918275
LP
69 struct timespec ts;
70
47be870b 71 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
72
73 return timespec_load(&ts);
74}
75
871d7de4
LP
76timestamp* timestamp_get(timestamp *ts) {
77 assert(ts);
78
79 ts->realtime = now(CLOCK_REALTIME);
80 ts->monotonic = now(CLOCK_MONOTONIC);
81
82 return ts;
83}
84
60918275
LP
85usec_t timespec_load(const struct timespec *ts) {
86 assert(ts);
87
88 return
89 (usec_t) ts->tv_sec * USEC_PER_SEC +
90 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
91}
92
93struct timespec *timespec_store(struct timespec *ts, usec_t u) {
94 assert(ts);
95
96 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
97 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
98
99 return ts;
100}
101
102usec_t timeval_load(const struct timeval *tv) {
103 assert(tv);
104
105 return
106 (usec_t) tv->tv_sec * USEC_PER_SEC +
107 (usec_t) tv->tv_usec;
108}
109
110struct timeval *timeval_store(struct timeval *tv, usec_t u) {
111 assert(tv);
112
113 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
114 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
115
116 return tv;
117}
118
119bool endswith(const char *s, const char *postfix) {
120 size_t sl, pl;
121
122 assert(s);
123 assert(postfix);
124
125 sl = strlen(s);
126 pl = strlen(postfix);
127
d4d0d4db
LP
128 if (pl == 0)
129 return true;
130
60918275
LP
131 if (sl < pl)
132 return false;
133
134 return memcmp(s + sl - pl, postfix, pl) == 0;
135}
136
137bool startswith(const char *s, const char *prefix) {
138 size_t sl, pl;
139
140 assert(s);
141 assert(prefix);
142
143 sl = strlen(s);
144 pl = strlen(prefix);
145
d4d0d4db
LP
146 if (pl == 0)
147 return true;
148
60918275
LP
149 if (sl < pl)
150 return false;
151
152 return memcmp(s, prefix, pl) == 0;
153}
154
3177a7fa
MAP
155bool startswith_no_case(const char *s, const char *prefix) {
156 size_t sl, pl;
157 unsigned i;
158
159 assert(s);
160 assert(prefix);
161
162 sl = strlen(s);
163 pl = strlen(prefix);
164
165 if (pl == 0)
166 return true;
167
168 if (sl < pl)
169 return false;
170
171 for(i = 0; i < pl; ++i) {
172 if (tolower(s[i]) != tolower(prefix[i]))
173 return false;
174 }
175
176 return true;
177}
178
79d6d816
LP
179bool first_word(const char *s, const char *word) {
180 size_t sl, wl;
181
182 assert(s);
183 assert(word);
184
185 sl = strlen(s);
186 wl = strlen(word);
187
188 if (sl < wl)
189 return false;
190
d4d0d4db
LP
191 if (wl == 0)
192 return true;
193
79d6d816
LP
194 if (memcmp(s, word, wl) != 0)
195 return false;
196
d4d0d4db
LP
197 return s[wl] == 0 ||
198 strchr(WHITESPACE, s[wl]);
79d6d816
LP
199}
200
42f4e3c4 201int close_nointr(int fd) {
60918275
LP
202 assert(fd >= 0);
203
204 for (;;) {
205 int r;
206
207 if ((r = close(fd)) >= 0)
208 return r;
209
210 if (errno != EINTR)
211 return r;
212 }
213}
85261803 214
85f136b5 215void close_nointr_nofail(int fd) {
80876c20 216 int saved_errno = errno;
85f136b5
LP
217
218 /* like close_nointr() but cannot fail, and guarantees errno
219 * is unchanged */
220
221 assert_se(close_nointr(fd) == 0);
80876c20
LP
222
223 errno = saved_errno;
85f136b5
LP
224}
225
5b6319dc
LP
226void close_many(const int fds[], unsigned n_fd) {
227 unsigned i;
228
229 for (i = 0; i < n_fd; i++)
230 close_nointr_nofail(fds[i]);
231}
232
85261803
LP
233int parse_boolean(const char *v) {
234 assert(v);
235
44d8db9e 236 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 237 return 1;
44d8db9e 238 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
239 return 0;
240
241 return -EINVAL;
242}
243
244int safe_atou(const char *s, unsigned *ret_u) {
245 char *x = NULL;
034c6ed7 246 unsigned long l;
85261803
LP
247
248 assert(s);
249 assert(ret_u);
250
251 errno = 0;
252 l = strtoul(s, &x, 0);
253
254 if (!x || *x || errno)
255 return errno ? -errno : -EINVAL;
256
034c6ed7 257 if ((unsigned long) (unsigned) l != l)
85261803
LP
258 return -ERANGE;
259
260 *ret_u = (unsigned) l;
261 return 0;
262}
263
264int safe_atoi(const char *s, int *ret_i) {
265 char *x = NULL;
034c6ed7 266 long l;
85261803
LP
267
268 assert(s);
269 assert(ret_i);
270
271 errno = 0;
272 l = strtol(s, &x, 0);
273
274 if (!x || *x || errno)
275 return errno ? -errno : -EINVAL;
276
034c6ed7 277 if ((long) (int) l != l)
85261803
LP
278 return -ERANGE;
279
034c6ed7
LP
280 *ret_i = (int) l;
281 return 0;
282}
283
284int safe_atolu(const char *s, long unsigned *ret_lu) {
285 char *x = NULL;
286 unsigned long l;
287
288 assert(s);
289 assert(ret_lu);
290
291 errno = 0;
292 l = strtoul(s, &x, 0);
293
294 if (!x || *x || errno)
295 return errno ? -errno : -EINVAL;
296
297 *ret_lu = l;
298 return 0;
299}
300
301int safe_atoli(const char *s, long int *ret_li) {
302 char *x = NULL;
303 long l;
304
305 assert(s);
306 assert(ret_li);
307
308 errno = 0;
309 l = strtol(s, &x, 0);
310
311 if (!x || *x || errno)
312 return errno ? -errno : -EINVAL;
313
314 *ret_li = l;
315 return 0;
316}
317
318int safe_atollu(const char *s, long long unsigned *ret_llu) {
319 char *x = NULL;
320 unsigned long long l;
321
322 assert(s);
323 assert(ret_llu);
324
325 errno = 0;
326 l = strtoull(s, &x, 0);
327
328 if (!x || *x || errno)
329 return errno ? -errno : -EINVAL;
330
331 *ret_llu = l;
332 return 0;
333}
334
335int safe_atolli(const char *s, long long int *ret_lli) {
336 char *x = NULL;
337 long long l;
338
339 assert(s);
340 assert(ret_lli);
341
342 errno = 0;
343 l = strtoll(s, &x, 0);
344
345 if (!x || *x || errno)
346 return errno ? -errno : -EINVAL;
347
348 *ret_lli = l;
85261803
LP
349 return 0;
350}
a41e8209 351
a41e8209 352/* Split a string into words. */
65d2ebdc 353char *split(const char *c, size_t *l, const char *separator, char **state) {
a41e8209
LP
354 char *current;
355
356 current = *state ? *state : (char*) c;
357
358 if (!*current || *c == 0)
359 return NULL;
360
65d2ebdc
LP
361 current += strspn(current, separator);
362 *l = strcspn(current, separator);
82919e3d
LP
363 *state = current+*l;
364
365 return (char*) current;
366}
367
034c6ed7
LP
368/* Split a string into words, but consider strings enclosed in '' and
369 * "" as words even if they include spaces. */
370char *split_quoted(const char *c, size_t *l, char **state) {
371 char *current;
372
373 current = *state ? *state : (char*) c;
374
375 if (!*current || *c == 0)
376 return NULL;
377
378 current += strspn(current, WHITESPACE);
379
380 if (*current == '\'') {
381 current ++;
382 *l = strcspn(current, "'");
383 *state = current+*l;
384
385 if (**state == '\'')
386 (*state)++;
387 } else if (*current == '\"') {
388 current ++;
b858b600 389 *l = strcspn(current, "\"");
034c6ed7
LP
390 *state = current+*l;
391
392 if (**state == '\"')
393 (*state)++;
394 } else {
395 *l = strcspn(current, WHITESPACE);
396 *state = current+*l;
397 }
398
44d8db9e
LP
399 /* FIXME: Cannot deal with strings that have spaces AND ticks
400 * in them */
401
034c6ed7
LP
402 return (char*) current;
403}
404
65d2ebdc
LP
405char **split_path_and_make_absolute(const char *p) {
406 char **l;
407 assert(p);
408
409 if (!(l = strv_split(p, ":")))
410 return NULL;
411
412 if (!strv_path_make_absolute_cwd(l)) {
413 strv_free(l);
414 return NULL;
415 }
416
417 return l;
418}
419
034c6ed7
LP
420int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
421 int r;
422 FILE *f;
423 char fn[132], line[256], *p;
424 long long unsigned ppid;
425
426 assert(pid >= 0);
427 assert(_ppid);
428
429 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%llu/stat", (unsigned long long) pid) < (int) (sizeof(fn)-1));
430 fn[sizeof(fn)-1] = 0;
431
432 if (!(f = fopen(fn, "r")))
433 return -errno;
434
435 if (!(fgets(line, sizeof(line), f))) {
436 r = -errno;
437 fclose(f);
438 return r;
439 }
440
441 fclose(f);
442
443 /* Let's skip the pid and comm fields. The latter is enclosed
444 * in () but does not escape any () in its value, so let's
445 * skip over it manually */
446
447 if (!(p = strrchr(line, ')')))
448 return -EIO;
449
450 p++;
451
452 if (sscanf(p, " "
453 "%*c " /* state */
454 "%llu ", /* ppid */
455 &ppid) != 1)
456 return -EIO;
457
458 if ((long long unsigned) (pid_t) ppid != ppid)
459 return -ERANGE;
460
461 *_ppid = (pid_t) ppid;
462
463 return 0;
464}
465
466int write_one_line_file(const char *fn, const char *line) {
467 FILE *f;
468 int r;
469
470 assert(fn);
471 assert(line);
472
473 if (!(f = fopen(fn, "we")))
474 return -errno;
475
476 if (fputs(line, f) < 0) {
477 r = -errno;
478 goto finish;
479 }
480
481 r = 0;
482finish:
483 fclose(f);
484 return r;
485}
486
487int read_one_line_file(const char *fn, char **line) {
488 FILE *f;
489 int r;
11316633 490 char t[2048], *c;
034c6ed7
LP
491
492 assert(fn);
493 assert(line);
494
495 if (!(f = fopen(fn, "re")))
496 return -errno;
497
498 if (!(fgets(t, sizeof(t), f))) {
499 r = -errno;
500 goto finish;
501 }
502
503 if (!(c = strdup(t))) {
504 r = -ENOMEM;
505 goto finish;
506 }
507
508 *line = c;
509 r = 0;
510
511finish:
512 fclose(f);
513 return r;
514}
44d8db9e 515
7072ced8
LP
516char *truncate_nl(char *s) {
517 assert(s);
518
519 s[strcspn(s, NEWLINE)] = 0;
520 return s;
521}
522
523int get_process_name(pid_t pid, char **name) {
524 char *p;
525 int r;
526
527 assert(pid >= 1);
528 assert(name);
529
530 if (asprintf(&p, "/proc/%llu/comm", (unsigned long long) pid) < 0)
531 return -ENOMEM;
532
533 r = read_one_line_file(p, name);
534 free(p);
535
536 if (r < 0)
537 return r;
538
539 truncate_nl(*name);
540 return 0;
541}
542
44d8db9e
LP
543char *strappend(const char *s, const char *suffix) {
544 size_t a, b;
545 char *r;
546
547 assert(s);
548 assert(suffix);
549
550 a = strlen(s);
551 b = strlen(suffix);
552
553 if (!(r = new(char, a+b+1)))
554 return NULL;
555
556 memcpy(r, s, a);
557 memcpy(r+a, suffix, b);
558 r[a+b] = 0;
559
560 return r;
561}
87f0e418
LP
562
563int readlink_malloc(const char *p, char **r) {
564 size_t l = 100;
565
566 assert(p);
567 assert(r);
568
569 for (;;) {
570 char *c;
571 ssize_t n;
572
573 if (!(c = new(char, l)))
574 return -ENOMEM;
575
576 if ((n = readlink(p, c, l-1)) < 0) {
577 int ret = -errno;
578 free(c);
579 return ret;
580 }
581
582 if ((size_t) n < l-1) {
583 c[n] = 0;
584 *r = c;
585 return 0;
586 }
587
588 free(c);
589 l *= 2;
590 }
591}
592
2c7108c4
LP
593int readlink_and_make_absolute(const char *p, char **r) {
594 char *target, *k;
595 int j;
596
597 assert(p);
598 assert(r);
599
600 if ((j = readlink_malloc(p, &target)) < 0)
601 return j;
602
603 k = file_in_same_dir(p, target);
604 free(target);
605
606 if (!k)
607 return -ENOMEM;
608
609 *r = k;
610 return 0;
611}
612
87f0e418
LP
613char *file_name_from_path(const char *p) {
614 char *r;
615
616 assert(p);
617
618 if ((r = strrchr(p, '/')))
619 return r + 1;
620
621 return (char*) p;
622}
0301abf4
LP
623
624bool path_is_absolute(const char *p) {
625 assert(p);
626
627 return p[0] == '/';
628}
629
630bool is_path(const char *p) {
631
632 return !!strchr(p, '/');
633}
634
635char *path_make_absolute(const char *p, const char *prefix) {
636 char *r;
637
638 assert(p);
639
65d2ebdc
LP
640 /* Makes every item in the list an absolute path by prepending
641 * the prefix, if specified and necessary */
642
0301abf4
LP
643 if (path_is_absolute(p) || !prefix)
644 return strdup(p);
645
646 if (asprintf(&r, "%s/%s", prefix, p) < 0)
647 return NULL;
648
649 return r;
650}
2a987ee8 651
65d2ebdc
LP
652char *path_make_absolute_cwd(const char *p) {
653 char *cwd, *r;
654
655 assert(p);
656
657 /* Similar to path_make_absolute(), but prefixes with the
658 * current working directory. */
659
660 if (path_is_absolute(p))
661 return strdup(p);
662
663 if (!(cwd = get_current_dir_name()))
664 return NULL;
665
666 r = path_make_absolute(p, cwd);
667 free(cwd);
668
669 return r;
670}
671
672char **strv_path_make_absolute_cwd(char **l) {
673 char **s;
674
675 /* Goes through every item in the string list and makes it
676 * absolute. This works in place and won't rollback any
677 * changes on failure. */
678
679 STRV_FOREACH(s, l) {
680 char *t;
681
682 if (!(t = path_make_absolute_cwd(*s)))
683 return NULL;
684
685 free(*s);
686 *s = t;
687 }
688
689 return l;
690}
691
c3f6d675
LP
692char **strv_path_canonicalize(char **l) {
693 char **s;
694 unsigned k = 0;
695 bool enomem = false;
696
697 if (strv_isempty(l))
698 return l;
699
700 /* Goes through every item in the string list and canonicalize
701 * the path. This works in place and won't rollback any
702 * changes on failure. */
703
704 STRV_FOREACH(s, l) {
705 char *t, *u;
706
707 t = path_make_absolute_cwd(*s);
708 free(*s);
709
710 if (!t) {
711 enomem = true;
712 continue;
713 }
714
715 errno = 0;
716 u = canonicalize_file_name(t);
717 free(t);
718
719 if (!u) {
720 if (errno == ENOMEM || !errno)
721 enomem = true;
722
723 continue;
724 }
725
726 l[k++] = u;
727 }
728
729 l[k] = NULL;
730
731 if (enomem)
732 return NULL;
733
734 return l;
735}
736
2a987ee8
LP
737int reset_all_signal_handlers(void) {
738 int sig;
739
740 for (sig = 1; sig < _NSIG; sig++) {
741 struct sigaction sa;
742
743 if (sig == SIGKILL || sig == SIGSTOP)
744 continue;
745
746 zero(sa);
747 sa.sa_handler = SIG_DFL;
431c32bf 748 sa.sa_flags = SA_RESTART;
2a987ee8
LP
749
750 /* On Linux the first two RT signals are reserved by
751 * glibc, and sigaction() will return EINVAL for them. */
752 if ((sigaction(sig, &sa, NULL) < 0))
753 if (errno != EINVAL)
754 return -errno;
755 }
756
8e274523 757 return 0;
2a987ee8 758}
4a72ff34
LP
759
760char *strstrip(char *s) {
761 char *e, *l = NULL;
762
763 /* Drops trailing whitespace. Modifies the string in
764 * place. Returns pointer to first non-space character */
765
766 s += strspn(s, WHITESPACE);
767
768 for (e = s; *e; e++)
769 if (!strchr(WHITESPACE, *e))
770 l = e;
771
772 if (l)
773 *(l+1) = 0;
774 else
775 *s = 0;
776
777 return s;
4a72ff34
LP
778}
779
ee9b5e01
LP
780char *delete_chars(char *s, const char *bad) {
781 char *f, *t;
782
783 /* Drops all whitespace, regardless where in the string */
784
785 for (f = s, t = s; *f; f++) {
786 if (strchr(bad, *f))
787 continue;
788
789 *(t++) = *f;
790 }
791
792 *t = 0;
793
794 return s;
795}
796
4a72ff34
LP
797char *file_in_same_dir(const char *path, const char *filename) {
798 char *e, *r;
799 size_t k;
800
801 assert(path);
802 assert(filename);
803
804 /* This removes the last component of path and appends
805 * filename, unless the latter is absolute anyway or the
806 * former isn't */
807
808 if (path_is_absolute(filename))
809 return strdup(filename);
810
811 if (!(e = strrchr(path, '/')))
812 return strdup(filename);
813
814 k = strlen(filename);
815 if (!(r = new(char, e-path+1+k+1)))
816 return NULL;
817
818 memcpy(r, path, e-path+1);
819 memcpy(r+(e-path)+1, filename, k+1);
820
821 return r;
822}
fb624d04 823
a9f5d454
LP
824int mkdir_parents(const char *path, mode_t mode) {
825 const char *p, *e;
826
827 assert(path);
828
829 /* Creates every parent directory in the path except the last
830 * component. */
831
832 p = path + strspn(path, "/");
833 for (;;) {
834 int r;
835 char *t;
836
837 e = p + strcspn(p, "/");
838 p = e + strspn(e, "/");
839
840 /* Is this the last component? If so, then we're
841 * done */
842 if (*p == 0)
843 return 0;
844
845 if (!(t = strndup(path, e - path)))
846 return -ENOMEM;
847
848 r = mkdir(t, mode);
849
850 free(t);
851
852 if (r < 0 && errno != EEXIST)
853 return -errno;
854 }
855}
856
bbd67135
LP
857int mkdir_p(const char *path, mode_t mode) {
858 int r;
859
860 /* Like mkdir -p */
861
862 if ((r = mkdir_parents(path, mode)) < 0)
863 return r;
864
865 if (mkdir(path, mode) < 0)
866 return -errno;
867
868 return 0;
869}
870
fb624d04
LP
871char hexchar(int x) {
872 static const char table[16] = "0123456789abcdef";
873
874 return table[x & 15];
875}
4fe88d28
LP
876
877int unhexchar(char c) {
878
879 if (c >= '0' && c <= '9')
880 return c - '0';
881
882 if (c >= 'a' && c <= 'f')
ea430986 883 return c - 'a' + 10;
4fe88d28
LP
884
885 if (c >= 'A' && c <= 'F')
ea430986 886 return c - 'A' + 10;
4fe88d28
LP
887
888 return -1;
889}
890
891char octchar(int x) {
892 return '0' + (x & 7);
893}
894
895int unoctchar(char c) {
896
897 if (c >= '0' && c <= '7')
898 return c - '0';
899
900 return -1;
901}
902
5af98f82
LP
903char decchar(int x) {
904 return '0' + (x % 10);
905}
906
907int undecchar(char c) {
908
909 if (c >= '0' && c <= '9')
910 return c - '0';
911
912 return -1;
913}
914
4fe88d28
LP
915char *cescape(const char *s) {
916 char *r, *t;
917 const char *f;
918
919 assert(s);
920
921 /* Does C style string escaping. */
922
923 if (!(r = new(char, strlen(s)*4 + 1)))
924 return NULL;
925
926 for (f = s, t = r; *f; f++)
927
928 switch (*f) {
929
930 case '\a':
931 *(t++) = '\\';
932 *(t++) = 'a';
933 break;
934 case '\b':
935 *(t++) = '\\';
936 *(t++) = 'b';
937 break;
938 case '\f':
939 *(t++) = '\\';
940 *(t++) = 'f';
941 break;
942 case '\n':
943 *(t++) = '\\';
944 *(t++) = 'n';
945 break;
946 case '\r':
947 *(t++) = '\\';
948 *(t++) = 'r';
949 break;
950 case '\t':
951 *(t++) = '\\';
952 *(t++) = 't';
953 break;
954 case '\v':
955 *(t++) = '\\';
956 *(t++) = 'v';
957 break;
958 case '\\':
959 *(t++) = '\\';
960 *(t++) = '\\';
961 break;
962 case '"':
963 *(t++) = '\\';
964 *(t++) = '"';
965 break;
966 case '\'':
967 *(t++) = '\\';
968 *(t++) = '\'';
969 break;
970
971 default:
972 /* For special chars we prefer octal over
973 * hexadecimal encoding, simply because glib's
974 * g_strescape() does the same */
975 if ((*f < ' ') || (*f >= 127)) {
976 *(t++) = '\\';
977 *(t++) = octchar((unsigned char) *f >> 6);
978 *(t++) = octchar((unsigned char) *f >> 3);
979 *(t++) = octchar((unsigned char) *f);
980 } else
981 *(t++) = *f;
982 break;
983 }
984
985 *t = 0;
986
987 return r;
988}
989
990char *cunescape(const char *s) {
991 char *r, *t;
992 const char *f;
993
994 assert(s);
995
996 /* Undoes C style string escaping */
997
998 if (!(r = new(char, strlen(s)+1)))
999 return r;
1000
1001 for (f = s, t = r; *f; f++) {
1002
1003 if (*f != '\\') {
1004 *(t++) = *f;
1005 continue;
1006 }
1007
1008 f++;
1009
1010 switch (*f) {
1011
1012 case 'a':
1013 *(t++) = '\a';
1014 break;
1015 case 'b':
1016 *(t++) = '\b';
1017 break;
1018 case 'f':
1019 *(t++) = '\f';
1020 break;
1021 case 'n':
1022 *(t++) = '\n';
1023 break;
1024 case 'r':
1025 *(t++) = '\r';
1026 break;
1027 case 't':
1028 *(t++) = '\t';
1029 break;
1030 case 'v':
1031 *(t++) = '\v';
1032 break;
1033 case '\\':
1034 *(t++) = '\\';
1035 break;
1036 case '"':
1037 *(t++) = '"';
1038 break;
1039 case '\'':
1040 *(t++) = '\'';
1041 break;
1042
1043 case 'x': {
1044 /* hexadecimal encoding */
1045 int a, b;
1046
1047 if ((a = unhexchar(f[1])) < 0 ||
1048 (b = unhexchar(f[2])) < 0) {
1049 /* Invalid escape code, let's take it literal then */
1050 *(t++) = '\\';
1051 *(t++) = 'x';
1052 } else {
1053 *(t++) = (char) ((a << 4) | b);
1054 f += 2;
1055 }
1056
1057 break;
1058 }
1059
1060 case '0':
1061 case '1':
1062 case '2':
1063 case '3':
1064 case '4':
1065 case '5':
1066 case '6':
1067 case '7': {
1068 /* octal encoding */
1069 int a, b, c;
1070
1071 if ((a = unoctchar(f[0])) < 0 ||
1072 (b = unoctchar(f[1])) < 0 ||
1073 (c = unoctchar(f[2])) < 0) {
1074 /* Invalid escape code, let's take it literal then */
1075 *(t++) = '\\';
1076 *(t++) = f[0];
1077 } else {
1078 *(t++) = (char) ((a << 6) | (b << 3) | c);
1079 f += 2;
1080 }
1081
1082 break;
1083 }
1084
1085 case 0:
1086 /* premature end of string.*/
1087 *(t++) = '\\';
1088 goto finish;
1089
1090 default:
1091 /* Invalid escape code, let's take it literal then */
1092 *(t++) = '\\';
1093 *(t++) = 'f';
1094 break;
1095 }
1096 }
1097
1098finish:
1099 *t = 0;
1100 return r;
1101}
1102
1103
1104char *xescape(const char *s, const char *bad) {
1105 char *r, *t;
1106 const char *f;
1107
1108 /* Escapes all chars in bad, in addition to \ and all special
1109 * chars, in \xFF style escaping. May be reversed with
1110 * cunescape. */
1111
1112 if (!(r = new(char, strlen(s)*4+1)))
1113 return NULL;
1114
1115 for (f = s, t = r; *f; f++) {
1116
b866264a
LP
1117 if ((*f < ' ') || (*f >= 127) ||
1118 (*f == '\\') || strchr(bad, *f)) {
4fe88d28
LP
1119 *(t++) = '\\';
1120 *(t++) = 'x';
1121 *(t++) = hexchar(*f >> 4);
1122 *(t++) = hexchar(*f);
1123 } else
1124 *(t++) = *f;
1125 }
1126
1127 *t = 0;
1128
1129 return r;
1130}
1131
ea430986 1132char *bus_path_escape(const char *s) {
ea430986
LP
1133 char *r, *t;
1134 const char *f;
1135
47be870b
LP
1136 assert(s);
1137
ea430986
LP
1138 /* Escapes all chars that D-Bus' object path cannot deal
1139 * with. Can be reverse with bus_path_unescape() */
1140
1141 if (!(r = new(char, strlen(s)*3+1)))
1142 return NULL;
1143
1144 for (f = s, t = r; *f; f++) {
1145
1146 if (!(*f >= 'A' && *f <= 'Z') &&
1147 !(*f >= 'a' && *f <= 'z') &&
1148 !(*f >= '0' && *f <= '9')) {
1149 *(t++) = '_';
1150 *(t++) = hexchar(*f >> 4);
1151 *(t++) = hexchar(*f);
1152 } else
1153 *(t++) = *f;
1154 }
1155
1156 *t = 0;
1157
1158 return r;
1159}
1160
9e2f7c11 1161char *bus_path_unescape(const char *f) {
ea430986 1162 char *r, *t;
ea430986 1163
9e2f7c11 1164 assert(f);
47be870b 1165
9e2f7c11 1166 if (!(r = strdup(f)))
ea430986
LP
1167 return NULL;
1168
9e2f7c11 1169 for (t = r; *f; f++) {
ea430986
LP
1170
1171 if (*f == '_') {
1172 int a, b;
1173
1174 if ((a = unhexchar(f[1])) < 0 ||
1175 (b = unhexchar(f[2])) < 0) {
1176 /* Invalid escape code, let's take it literal then */
1177 *(t++) = '_';
1178 } else {
1179 *(t++) = (char) ((a << 4) | b);
1180 f += 2;
1181 }
1182 } else
1183 *(t++) = *f;
1184 }
1185
1186 *t = 0;
1187
1188 return r;
1189}
1190
4fe88d28
LP
1191char *path_kill_slashes(char *path) {
1192 char *f, *t;
1193 bool slash = false;
1194
1195 /* Removes redundant inner and trailing slashes. Modifies the
1196 * passed string in-place.
1197 *
1198 * ///foo///bar/ becomes /foo/bar
1199 */
1200
1201 for (f = path, t = path; *f; f++) {
1202
1203 if (*f == '/') {
1204 slash = true;
1205 continue;
1206 }
1207
1208 if (slash) {
1209 slash = false;
1210 *(t++) = '/';
1211 }
1212
1213 *(t++) = *f;
1214 }
1215
1216 /* Special rule, if we are talking of the root directory, a
1217 trailing slash is good */
1218
1219 if (t == path && slash)
1220 *(t++) = '/';
1221
1222 *t = 0;
1223 return path;
1224}
1225
1226bool path_startswith(const char *path, const char *prefix) {
1227 assert(path);
1228 assert(prefix);
1229
1230 if ((path[0] == '/') != (prefix[0] == '/'))
1231 return false;
1232
1233 for (;;) {
1234 size_t a, b;
1235
1236 path += strspn(path, "/");
1237 prefix += strspn(prefix, "/");
1238
1239 if (*prefix == 0)
1240 return true;
1241
1242 if (*path == 0)
1243 return false;
1244
1245 a = strcspn(path, "/");
1246 b = strcspn(prefix, "/");
1247
1248 if (a != b)
1249 return false;
1250
1251 if (memcmp(path, prefix, a) != 0)
1252 return false;
1253
1254 path += a;
1255 prefix += b;
1256 }
1257}
1258
15ae422b
LP
1259bool path_equal(const char *a, const char *b) {
1260 assert(a);
1261 assert(b);
1262
1263 if ((a[0] == '/') != (b[0] == '/'))
1264 return false;
1265
1266 for (;;) {
1267 size_t j, k;
1268
1269 a += strspn(a, "/");
1270 b += strspn(b, "/");
1271
1272 if (*a == 0 && *b == 0)
1273 return true;
1274
1275 if (*a == 0 || *b == 0)
1276 return false;
1277
1278 j = strcspn(a, "/");
1279 k = strcspn(b, "/");
1280
1281 if (j != k)
1282 return false;
1283
1284 if (memcmp(a, b, j) != 0)
1285 return false;
1286
1287 a += j;
1288 b += k;
1289 }
1290}
1291
67d51650 1292char *ascii_strlower(char *t) {
4fe88d28
LP
1293 char *p;
1294
67d51650 1295 assert(t);
4fe88d28 1296
67d51650 1297 for (p = t; *p; p++)
4fe88d28
LP
1298 if (*p >= 'A' && *p <= 'Z')
1299 *p = *p - 'A' + 'a';
1300
67d51650 1301 return t;
4fe88d28 1302}
1dccbe19 1303
c85dc17b
LP
1304bool ignore_file(const char *filename) {
1305 assert(filename);
1306
1307 return
1308 filename[0] == '.' ||
6c78be3c 1309 streq(filename, "lost+found") ||
c85dc17b
LP
1310 endswith(filename, "~") ||
1311 endswith(filename, ".rpmnew") ||
1312 endswith(filename, ".rpmsave") ||
1313 endswith(filename, ".rpmorig") ||
1314 endswith(filename, ".dpkg-old") ||
1315 endswith(filename, ".dpkg-new") ||
1316 endswith(filename, ".swp");
1317}
1318
3a0ecb08
LP
1319int fd_nonblock(int fd, bool nonblock) {
1320 int flags;
1321
1322 assert(fd >= 0);
1323
1324 if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1325 return -errno;
1326
1327 if (nonblock)
1328 flags |= O_NONBLOCK;
1329 else
1330 flags &= ~O_NONBLOCK;
1331
1332 if (fcntl(fd, F_SETFL, flags) < 0)
1333 return -errno;
1334
1335 return 0;
1336}
1337
1338int fd_cloexec(int fd, bool cloexec) {
1339 int flags;
1340
1341 assert(fd >= 0);
1342
1343 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
1344 return -errno;
1345
1346 if (cloexec)
1347 flags |= FD_CLOEXEC;
1348 else
1349 flags &= ~FD_CLOEXEC;
1350
1351 if (fcntl(fd, F_SETFD, flags) < 0)
1352 return -errno;
1353
1354 return 0;
1355}
1356
a0d40ac5
LP
1357int close_all_fds(const int except[], unsigned n_except) {
1358 DIR *d;
1359 struct dirent *de;
1360 int r = 0;
1361
1362 if (!(d = opendir("/proc/self/fd")))
1363 return -errno;
1364
1365 while ((de = readdir(d))) {
a7610064 1366 int fd = -1;
a0d40ac5 1367
a16e1123 1368 if (ignore_file(de->d_name))
a0d40ac5
LP
1369 continue;
1370
1371 if ((r = safe_atoi(de->d_name, &fd)) < 0)
1372 goto finish;
1373
1374 if (fd < 3)
1375 continue;
1376
1377 if (fd == dirfd(d))
1378 continue;
1379
1380 if (except) {
1381 bool found;
1382 unsigned i;
1383
1384 found = false;
1385 for (i = 0; i < n_except; i++)
1386 if (except[i] == fd) {
1387 found = true;
1388 break;
1389 }
1390
1391 if (found)
1392 continue;
1393 }
1394
2f357920
LP
1395 if ((r = close_nointr(fd)) < 0) {
1396 /* Valgrind has its own FD and doesn't want to have it closed */
1397 if (errno != EBADF)
1398 goto finish;
1399 }
a0d40ac5
LP
1400 }
1401
2f357920
LP
1402 r = 0;
1403
a0d40ac5
LP
1404finish:
1405 closedir(d);
1406 return r;
1407}
1408
db12775d
LP
1409bool chars_intersect(const char *a, const char *b) {
1410 const char *p;
1411
1412 /* Returns true if any of the chars in a are in b. */
1413 for (p = a; *p; p++)
1414 if (strchr(b, *p))
1415 return true;
1416
1417 return false;
1418}
1419
8b6c7120
LP
1420char *format_timestamp(char *buf, size_t l, usec_t t) {
1421 struct tm tm;
1422 time_t sec;
1423
1424 assert(buf);
1425 assert(l > 0);
1426
1427 if (t <= 0)
1428 return NULL;
1429
1430 sec = (time_t) t / USEC_PER_SEC;
1431
1432 if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
1433 return NULL;
1434
1435 return buf;
1436}
1437
871d7de4
LP
1438char *format_timespan(char *buf, size_t l, usec_t t) {
1439 static const struct {
1440 const char *suffix;
1441 usec_t usec;
1442 } table[] = {
1443 { "w", USEC_PER_WEEK },
1444 { "d", USEC_PER_DAY },
1445 { "h", USEC_PER_HOUR },
1446 { "min", USEC_PER_MINUTE },
1447 { "s", USEC_PER_SEC },
1448 { "ms", USEC_PER_MSEC },
1449 { "us", 1 },
1450 };
1451
1452 unsigned i;
1453 char *p = buf;
1454
1455 assert(buf);
1456 assert(l > 0);
1457
1458 if (t == (usec_t) -1)
1459 return NULL;
1460
1461 /* The result of this function can be parsed with parse_usec */
1462
1463 for (i = 0; i < ELEMENTSOF(table); i++) {
1464 int k;
1465 size_t n;
1466
1467 if (t < table[i].usec)
1468 continue;
1469
1470 if (l <= 1)
1471 break;
1472
1473 k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
1474 n = MIN((size_t) k, l);
1475
1476 l -= n;
1477 p += n;
1478
1479 t %= table[i].usec;
1480 }
1481
1482 *p = 0;
1483
1484 return buf;
1485}
1486
42856c10
LP
1487bool fstype_is_network(const char *fstype) {
1488 static const char * const table[] = {
1489 "cifs",
1490 "smbfs",
1491 "ncpfs",
1492 "nfs",
ca139f94
LP
1493 "nfs4",
1494 "gfs",
1495 "gfs2"
42856c10
LP
1496 };
1497
1498 unsigned i;
1499
1500 for (i = 0; i < ELEMENTSOF(table); i++)
1501 if (streq(table[i], fstype))
1502 return true;
1503
1504 return false;
1505}
1506
601f6a1e
LP
1507int chvt(int vt) {
1508 int fd, r = 0;
1509
1510 if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
1511 return -errno;
1512
1513 if (vt < 0) {
1514 int tiocl[2] = {
1515 TIOCL_GETKMSGREDIRECT,
1516 0
1517 };
1518
1519 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
1520 return -errno;
1521
1522 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
1523 }
1524
1525 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
1526 r = -errno;
1527
a16e1123 1528 close_nointr_nofail(r);
601f6a1e
LP
1529 return r;
1530}
1531
80876c20
LP
1532int read_one_char(FILE *f, char *ret, bool *need_nl) {
1533 struct termios old_termios, new_termios;
1534 char c;
1535 char line[1024];
1536
1537 assert(f);
1538 assert(ret);
1539
1540 if (tcgetattr(fileno(f), &old_termios) >= 0) {
1541 new_termios = old_termios;
1542
1543 new_termios.c_lflag &= ~ICANON;
1544 new_termios.c_cc[VMIN] = 1;
1545 new_termios.c_cc[VTIME] = 0;
1546
1547 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
1548 size_t k;
1549
1550 k = fread(&c, 1, 1, f);
1551
1552 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
1553
1554 if (k <= 0)
1555 return -EIO;
1556
1557 if (need_nl)
1558 *need_nl = c != '\n';
1559
1560 *ret = c;
1561 return 0;
1562 }
1563 }
1564
1565 if (!(fgets(line, sizeof(line), f)))
1566 return -EIO;
1567
1568 truncate_nl(line);
1569
1570 if (strlen(line) != 1)
1571 return -EBADMSG;
1572
1573 if (need_nl)
1574 *need_nl = false;
1575
1576 *ret = line[0];
1577 return 0;
1578}
1579
1580int ask(char *ret, const char *replies, const char *text, ...) {
1581 assert(ret);
1582 assert(replies);
1583 assert(text);
1584
1585 for (;;) {
1586 va_list ap;
1587 char c;
1588 int r;
1589 bool need_nl = true;
1590
b1b2dc0c
LP
1591 fputs("\x1B[1m", stdout);
1592
80876c20
LP
1593 va_start(ap, text);
1594 vprintf(text, ap);
1595 va_end(ap);
1596
b1b2dc0c
LP
1597 fputs("\x1B[0m", stdout);
1598
80876c20
LP
1599 fflush(stdout);
1600
1601 if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
1602
1603 if (r == -EBADMSG) {
1604 puts("Bad input, please try again.");
1605 continue;
1606 }
1607
1608 putchar('\n');
1609 return r;
1610 }
1611
1612 if (need_nl)
1613 putchar('\n');
1614
1615 if (strchr(replies, c)) {
1616 *ret = c;
1617 return 0;
1618 }
1619
1620 puts("Read unexpected character, please try again.");
1621 }
1622}
1623
1624int reset_terminal(int fd) {
1625 struct termios termios;
1626 int r = 0;
1627
1628 assert(fd >= 0);
1629
aaf694ca 1630 /* Set terminal to some sane defaults */
80876c20
LP
1631
1632 if (tcgetattr(fd, &termios) < 0) {
1633 r = -errno;
1634 goto finish;
1635 }
1636
aaf694ca
LP
1637 /* We only reset the stuff that matters to the software. How
1638 * hardware is set up we don't touch assuming that somebody
1639 * else will do that for us */
1640
1641 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
80876c20
LP
1642 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
1643 termios.c_oflag |= ONLCR;
1644 termios.c_cflag |= CREAD;
1645 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
1646
1647 termios.c_cc[VINTR] = 03; /* ^C */
1648 termios.c_cc[VQUIT] = 034; /* ^\ */
1649 termios.c_cc[VERASE] = 0177;
1650 termios.c_cc[VKILL] = 025; /* ^X */
1651 termios.c_cc[VEOF] = 04; /* ^D */
1652 termios.c_cc[VSTART] = 021; /* ^Q */
1653 termios.c_cc[VSTOP] = 023; /* ^S */
1654 termios.c_cc[VSUSP] = 032; /* ^Z */
1655 termios.c_cc[VLNEXT] = 026; /* ^V */
1656 termios.c_cc[VWERASE] = 027; /* ^W */
1657 termios.c_cc[VREPRINT] = 022; /* ^R */
aaf694ca
LP
1658 termios.c_cc[VEOL] = 0;
1659 termios.c_cc[VEOL2] = 0;
80876c20
LP
1660
1661 termios.c_cc[VTIME] = 0;
1662 termios.c_cc[VMIN] = 1;
1663
1664 if (tcsetattr(fd, TCSANOW, &termios) < 0)
1665 r = -errno;
1666
1667finish:
1668 /* Just in case, flush all crap out */
1669 tcflush(fd, TCIOFLUSH);
1670
1671 return r;
1672}
1673
1674int open_terminal(const char *name, int mode) {
1675 int fd, r;
1676
1677 if ((fd = open(name, mode)) < 0)
1678 return -errno;
1679
1680 if ((r = isatty(fd)) < 0) {
1681 close_nointr_nofail(fd);
1682 return -errno;
1683 }
1684
1685 if (!r) {
1686 close_nointr_nofail(fd);
1687 return -ENOTTY;
1688 }
1689
1690 return fd;
1691}
1692
1693int flush_fd(int fd) {
1694 struct pollfd pollfd;
1695
1696 zero(pollfd);
1697 pollfd.fd = fd;
1698 pollfd.events = POLLIN;
1699
1700 for (;;) {
1701 char buf[1024];
1702 ssize_t l;
1703 int r;
1704
1705 if ((r = poll(&pollfd, 1, 0)) < 0) {
1706
1707 if (errno == EINTR)
1708 continue;
1709
1710 return -errno;
1711 }
1712
1713 if (r == 0)
1714 return 0;
1715
1716 if ((l = read(fd, buf, sizeof(buf))) < 0) {
1717
1718 if (errno == EINTR)
1719 continue;
1720
1721 if (errno == EAGAIN)
1722 return 0;
1723
1724 return -errno;
1725 }
1726
1727 if (l <= 0)
1728 return 0;
1729 }
1730}
1731
21de3988 1732int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm) {
bab45044 1733 int fd = -1, notify = -1, r, wd = -1;
80876c20
LP
1734
1735 assert(name);
1736
1737 /* We use inotify to be notified when the tty is closed. We
1738 * create the watch before checking if we can actually acquire
1739 * it, so that we don't lose any event.
1740 *
1741 * Note: strictly speaking this actually watches for the
1742 * device being closed, it does *not* really watch whether a
1743 * tty loses its controlling process. However, unless some
1744 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
1745 * its tty otherwise this will not become a problem. As long
1746 * as the administrator makes sure not configure any service
1747 * on the same tty as an untrusted user this should not be a
1748 * problem. (Which he probably should not do anyway.) */
1749
1750 if (!fail && !force) {
1751 if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
1752 r = -errno;
1753 goto fail;
1754 }
1755
1756 if ((wd = inotify_add_watch(notify, name, IN_CLOSE)) < 0) {
1757 r = -errno;
1758 goto fail;
1759 }
1760 }
1761
1762 for (;;) {
e3d1855b
LP
1763 if (notify >= 0)
1764 if ((r = flush_fd(notify)) < 0)
1765 goto fail;
80876c20
LP
1766
1767 /* We pass here O_NOCTTY only so that we can check the return
1768 * value TIOCSCTTY and have a reliable way to figure out if we
1769 * successfully became the controlling process of the tty */
1770 if ((fd = open_terminal(name, O_RDWR|O_NOCTTY)) < 0)
1771 return -errno;
1772
1773 /* First, try to get the tty */
21de3988
LP
1774 r = ioctl(fd, TIOCSCTTY, force);
1775
1776 /* Sometimes it makes sense to ignore TIOCSCTTY
1777 * returning EPERM, i.e. when very likely we already
1778 * are have this controlling terminal. */
1779 if (r < 0 && errno == EPERM && ignore_tiocstty_eperm)
1780 r = 0;
1781
1782 if (r < 0 && (force || fail || errno != EPERM)) {
80876c20
LP
1783 r = -errno;
1784 goto fail;
1785 }
1786
1787 if (r >= 0)
1788 break;
1789
1790 assert(!fail);
1791 assert(!force);
1792 assert(notify >= 0);
1793
1794 for (;;) {
1795 struct inotify_event e;
1796 ssize_t l;
1797
1798 if ((l = read(notify, &e, sizeof(e))) != sizeof(e)) {
1799
1800 if (l < 0) {
1801
1802 if (errno == EINTR)
1803 continue;
1804
1805 r = -errno;
1806 } else
1807 r = -EIO;
1808
1809 goto fail;
1810 }
1811
1812 if (e.wd != wd || !(e.mask & IN_CLOSE)) {
1813 r = -errno;
1814 goto fail;
1815 }
1816
1817 break;
1818 }
1819
1820 /* We close the tty fd here since if the old session
1821 * ended our handle will be dead. It's important that
1822 * we do this after sleeping, so that we don't enter
1823 * an endless loop. */
1824 close_nointr_nofail(fd);
1825 }
1826
1827 if (notify >= 0)
a16e1123 1828 close_nointr_nofail(notify);
80876c20
LP
1829
1830 if ((r = reset_terminal(fd)) < 0)
1831 log_warning("Failed to reset terminal: %s", strerror(-r));
1832
1833 return fd;
1834
1835fail:
1836 if (fd >= 0)
a16e1123 1837 close_nointr_nofail(fd);
80876c20
LP
1838
1839 if (notify >= 0)
a16e1123 1840 close_nointr_nofail(notify);
80876c20
LP
1841
1842 return r;
1843}
1844
1845int release_terminal(void) {
1846 int r = 0, fd;
57cd2192 1847 struct sigaction sa_old, sa_new;
80876c20 1848
57cd2192 1849 if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
80876c20
LP
1850 return -errno;
1851
57cd2192
LP
1852 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
1853 * by our own TIOCNOTTY */
1854
1855 zero(sa_new);
1856 sa_new.sa_handler = SIG_IGN;
1857 sa_new.sa_flags = SA_RESTART;
1858 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
1859
80876c20
LP
1860 if (ioctl(fd, TIOCNOTTY) < 0)
1861 r = -errno;
1862
57cd2192
LP
1863 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
1864
80876c20
LP
1865 close_nointr_nofail(fd);
1866 return r;
1867}
1868
9a34ec5f
LP
1869int sigaction_many(const struct sigaction *sa, ...) {
1870 va_list ap;
1871 int r = 0, sig;
1872
1873 va_start(ap, sa);
1874 while ((sig = va_arg(ap, int)) > 0)
1875 if (sigaction(sig, sa, NULL) < 0)
1876 r = -errno;
1877 va_end(ap);
1878
1879 return r;
1880}
1881
1882int ignore_signals(int sig, ...) {
a337c6fc 1883 struct sigaction sa;
9a34ec5f
LP
1884 va_list ap;
1885 int r = 0;
a337c6fc
LP
1886
1887 zero(sa);
1888 sa.sa_handler = SIG_IGN;
1889 sa.sa_flags = SA_RESTART;
1890
9a34ec5f
LP
1891 if (sigaction(sig, &sa, NULL) < 0)
1892 r = -errno;
1893
1894 va_start(ap, sig);
1895 while ((sig = va_arg(ap, int)) > 0)
1896 if (sigaction(sig, &sa, NULL) < 0)
1897 r = -errno;
1898 va_end(ap);
1899
1900 return r;
1901}
1902
1903int default_signals(int sig, ...) {
1904 struct sigaction sa;
1905 va_list ap;
1906 int r = 0;
1907
1908 zero(sa);
1909 sa.sa_handler = SIG_DFL;
1910 sa.sa_flags = SA_RESTART;
1911
1912 if (sigaction(sig, &sa, NULL) < 0)
1913 r = -errno;
1914
1915 va_start(ap, sig);
1916 while ((sig = va_arg(ap, int)) > 0)
1917 if (sigaction(sig, &sa, NULL) < 0)
1918 r = -errno;
1919 va_end(ap);
1920
1921 return r;
a337c6fc
LP
1922}
1923
8d567588
LP
1924int close_pipe(int p[]) {
1925 int a = 0, b = 0;
1926
1927 assert(p);
1928
1929 if (p[0] >= 0) {
1930 a = close_nointr(p[0]);
1931 p[0] = -1;
1932 }
1933
1934 if (p[1] >= 0) {
1935 b = close_nointr(p[1]);
1936 p[1] = -1;
1937 }
1938
1939 return a < 0 ? a : b;
1940}
1941
1942ssize_t loop_read(int fd, void *buf, size_t nbytes) {
1943 uint8_t *p;
1944 ssize_t n = 0;
1945
1946 assert(fd >= 0);
1947 assert(buf);
1948
1949 p = buf;
1950
1951 while (nbytes > 0) {
1952 ssize_t k;
1953
1954 if ((k = read(fd, p, nbytes)) <= 0) {
1955
1956 if (errno == EINTR)
1957 continue;
1958
1959 if (errno == EAGAIN) {
1960 struct pollfd pollfd;
1961
1962 zero(pollfd);
1963 pollfd.fd = fd;
1964 pollfd.events = POLLIN;
1965
1966 if (poll(&pollfd, 1, -1) < 0) {
1967 if (errno == EINTR)
1968 continue;
1969
1970 return n > 0 ? n : -errno;
1971 }
1972
1973 if (pollfd.revents != POLLIN)
1974 return n > 0 ? n : -EIO;
1975
1976 continue;
1977 }
1978
1979 return n > 0 ? n : (k < 0 ? -errno : 0);
1980 }
1981
1982 p += k;
1983 nbytes -= k;
1984 n += k;
1985 }
1986
1987 return n;
1988}
1989
1990int path_is_mount_point(const char *t) {
1991 struct stat a, b;
1992 char *copy;
1993
1994 if (lstat(t, &a) < 0) {
1995
1996 if (errno == ENOENT)
1997 return 0;
1998
1999 return -errno;
2000 }
2001
2002 if (!(copy = strdup(t)))
2003 return -ENOMEM;
2004
2005 if (lstat(dirname(copy), &b) < 0) {
2006 free(copy);
2007 return -errno;
2008 }
2009
2010 free(copy);
2011
2012 return a.st_dev != b.st_dev;
2013}
2014
24a6e4a4
LP
2015int parse_usec(const char *t, usec_t *usec) {
2016 static const struct {
2017 const char *suffix;
2018 usec_t usec;
2019 } table[] = {
2020 { "sec", USEC_PER_SEC },
2021 { "s", USEC_PER_SEC },
2022 { "min", USEC_PER_MINUTE },
2023 { "hr", USEC_PER_HOUR },
2024 { "h", USEC_PER_HOUR },
2025 { "d", USEC_PER_DAY },
2026 { "w", USEC_PER_WEEK },
2027 { "msec", USEC_PER_MSEC },
2028 { "ms", USEC_PER_MSEC },
2029 { "m", USEC_PER_MINUTE },
2030 { "usec", 1ULL },
2031 { "us", 1ULL },
2032 { "", USEC_PER_SEC },
2033 };
2034
2035 const char *p;
2036 usec_t r = 0;
2037
2038 assert(t);
2039 assert(usec);
2040
2041 p = t;
2042 do {
2043 long long l;
2044 char *e;
2045 unsigned i;
2046
2047 errno = 0;
2048 l = strtoll(p, &e, 10);
2049
2050 if (errno != 0)
2051 return -errno;
2052
2053 if (l < 0)
2054 return -ERANGE;
2055
2056 if (e == p)
2057 return -EINVAL;
2058
2059 e += strspn(e, WHITESPACE);
2060
2061 for (i = 0; i < ELEMENTSOF(table); i++)
2062 if (startswith(e, table[i].suffix)) {
2063 r += (usec_t) l * table[i].usec;
2064 p = e + strlen(table[i].suffix);
2065 break;
2066 }
2067
2068 if (i >= ELEMENTSOF(table))
2069 return -EINVAL;
2070
2071 } while (*p != 0);
2072
2073 *usec = r;
2074
2075 return 0;
2076}
2077
843d2643
LP
2078int make_stdio(int fd) {
2079 int r, s, t;
2080
2081 assert(fd >= 0);
2082
2083 r = dup2(fd, STDIN_FILENO);
2084 s = dup2(fd, STDOUT_FILENO);
2085 t = dup2(fd, STDERR_FILENO);
2086
2087 if (fd >= 3)
2088 close_nointr_nofail(fd);
2089
2090 if (r < 0 || s < 0 || t < 0)
2091 return -errno;
2092
2093 return 0;
2094}
2095
cb8a8f78
LP
2096bool is_clean_exit(int code, int status) {
2097
2098 if (code == CLD_EXITED)
2099 return status == 0;
2100
2101 /* If a daemon does not implement handlers for some of the
2102 * signals that's not considered an unclean shutdown */
2103 if (code == CLD_KILLED)
2104 return
2105 status == SIGHUP ||
2106 status == SIGINT ||
2107 status == SIGTERM ||
2108 status == SIGPIPE;
2109
2110 return false;
2111}
2112
8407a5d0
LP
2113bool is_device_path(const char *path) {
2114
2115 /* Returns true on paths that refer to a device, either in
2116 * sysfs or in /dev */
2117
2118 return
2119 path_startswith(path, "/dev/") ||
2120 path_startswith(path, "/sys/");
2121}
2122
01f78473
LP
2123int dir_is_empty(const char *path) {
2124 DIR *d;
2125 int r;
2126 struct dirent buf, *de;
2127
2128 if (!(d = opendir(path)))
2129 return -errno;
2130
2131 for (;;) {
2132 if ((r = readdir_r(d, &buf, &de)) > 0) {
2133 r = -r;
2134 break;
2135 }
2136
2137 if (!de) {
2138 r = 1;
2139 break;
2140 }
2141
2142 if (!ignore_file(de->d_name)) {
2143 r = 0;
2144 break;
2145 }
2146 }
2147
2148 closedir(d);
2149 return r;
2150}
2151
d3782d60
LP
2152unsigned long long random_ull(void) {
2153 int fd;
2154 uint64_t ull;
2155 ssize_t r;
2156
2157 if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0)
2158 goto fallback;
2159
2160 r = loop_read(fd, &ull, sizeof(ull));
2161 close_nointr_nofail(fd);
2162
2163 if (r != sizeof(ull))
2164 goto fallback;
2165
2166 return ull;
2167
2168fallback:
2169 return random() * RAND_MAX + random();
2170}
2171
5b6319dc
LP
2172void rename_process(const char name[8]) {
2173 assert(name);
2174
2175 prctl(PR_SET_NAME, name);
2176
2177 /* This is a like a poor man's setproctitle(). The string
2178 * passed should fit in 7 chars (i.e. the length of
2179 * "systemd") */
2180
2181 if (program_invocation_name)
2182 strncpy(program_invocation_name, name, strlen(program_invocation_name));
2183}
2184
1dccbe19
LP
2185static const char *const ioprio_class_table[] = {
2186 [IOPRIO_CLASS_NONE] = "none",
2187 [IOPRIO_CLASS_RT] = "realtime",
2188 [IOPRIO_CLASS_BE] = "best-effort",
2189 [IOPRIO_CLASS_IDLE] = "idle"
2190};
2191
2192DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
2193
2194static const char *const sigchld_code_table[] = {
2195 [CLD_EXITED] = "exited",
2196 [CLD_KILLED] = "killed",
2197 [CLD_DUMPED] = "dumped",
2198 [CLD_TRAPPED] = "trapped",
2199 [CLD_STOPPED] = "stopped",
2200 [CLD_CONTINUED] = "continued",
2201};
2202
2203DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
2204
2205static const char *const log_facility_table[LOG_NFACILITIES] = {
2206 [LOG_FAC(LOG_KERN)] = "kern",
2207 [LOG_FAC(LOG_USER)] = "user",
2208 [LOG_FAC(LOG_MAIL)] = "mail",
2209 [LOG_FAC(LOG_DAEMON)] = "daemon",
2210 [LOG_FAC(LOG_AUTH)] = "auth",
2211 [LOG_FAC(LOG_SYSLOG)] = "syslog",
2212 [LOG_FAC(LOG_LPR)] = "lpr",
2213 [LOG_FAC(LOG_NEWS)] = "news",
2214 [LOG_FAC(LOG_UUCP)] = "uucp",
2215 [LOG_FAC(LOG_CRON)] = "cron",
2216 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
2217 [LOG_FAC(LOG_FTP)] = "ftp",
2218 [LOG_FAC(LOG_LOCAL0)] = "local0",
2219 [LOG_FAC(LOG_LOCAL1)] = "local1",
2220 [LOG_FAC(LOG_LOCAL2)] = "local2",
2221 [LOG_FAC(LOG_LOCAL3)] = "local3",
2222 [LOG_FAC(LOG_LOCAL4)] = "local4",
2223 [LOG_FAC(LOG_LOCAL5)] = "local5",
2224 [LOG_FAC(LOG_LOCAL6)] = "local6",
2225 [LOG_FAC(LOG_LOCAL7)] = "local7"
2226};
2227
2228DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
2229
2230static const char *const log_level_table[] = {
2231 [LOG_EMERG] = "emerg",
2232 [LOG_ALERT] = "alert",
2233 [LOG_CRIT] = "crit",
2234 [LOG_ERR] = "err",
2235 [LOG_WARNING] = "warning",
2236 [LOG_NOTICE] = "notice",
2237 [LOG_INFO] = "info",
2238 [LOG_DEBUG] = "debug"
2239};
2240
2241DEFINE_STRING_TABLE_LOOKUP(log_level, int);
2242
2243static const char* const sched_policy_table[] = {
2244 [SCHED_OTHER] = "other",
2245 [SCHED_BATCH] = "batch",
2246 [SCHED_IDLE] = "idle",
2247 [SCHED_FIFO] = "fifo",
2248 [SCHED_RR] = "rr"
2249};
2250
2251DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
2252
2253static const char* const rlimit_table[] = {
2254 [RLIMIT_CPU] = "LimitCPU",
2255 [RLIMIT_FSIZE] = "LimitFSIZE",
2256 [RLIMIT_DATA] = "LimitDATA",
2257 [RLIMIT_STACK] = "LimitSTACK",
2258 [RLIMIT_CORE] = "LimitCORE",
2259 [RLIMIT_RSS] = "LimitRSS",
2260 [RLIMIT_NOFILE] = "LimitNOFILE",
2261 [RLIMIT_AS] = "LimitAS",
2262 [RLIMIT_NPROC] = "LimitNPROC",
2263 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
2264 [RLIMIT_LOCKS] = "LimitLOCKS",
2265 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
2266 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
2267 [RLIMIT_NICE] = "LimitNICE",
2268 [RLIMIT_RTPRIO] = "LimitRTPRIO",
2269 [RLIMIT_RTTIME] = "LimitRTTIME"
2270};
2271
2272DEFINE_STRING_TABLE_LOOKUP(rlimit, int);