chiark / gitweb /
support chrooting/setting of ioprio when spawning
[elogind.git] / util.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 #include <assert.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <errno.h>
7 #include <stdlib.h>
8 #include <signal.h>
9 #include <stdio.h>
10
11 #include "macro.h"
12 #include "util.h"
13
14 usec_t now(clockid_t clock) {
15         struct timespec ts;
16
17         assert_se(clock_gettime(clock, &ts) == 0);
18
19         return timespec_load(&ts);
20 }
21
22 usec_t timespec_load(const struct timespec *ts) {
23         assert(ts);
24
25         return
26                 (usec_t) ts->tv_sec * USEC_PER_SEC +
27                 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
28 }
29
30 struct timespec *timespec_store(struct timespec *ts, usec_t u)  {
31         assert(ts);
32
33         ts->tv_sec = (time_t) (u / USEC_PER_SEC);
34         ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
35
36         return ts;
37 }
38
39 usec_t timeval_load(const struct timeval *tv) {
40         assert(tv);
41
42         return
43                 (usec_t) tv->tv_sec * USEC_PER_SEC +
44                 (usec_t) tv->tv_usec;
45 }
46
47 struct timeval *timeval_store(struct timeval *tv, usec_t u) {
48         assert(tv);
49
50         tv->tv_sec = (time_t) (u / USEC_PER_SEC);
51         tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
52
53         return tv;
54 }
55
56 bool endswith(const char *s, const char *postfix) {
57         size_t sl, pl;
58
59         assert(s);
60         assert(postfix);
61
62         sl = strlen(s);
63         pl = strlen(postfix);
64
65         if (sl < pl)
66                 return false;
67
68         return memcmp(s + sl - pl, postfix, pl) == 0;
69 }
70
71 bool startswith(const char *s, const char *prefix) {
72         size_t sl, pl;
73
74         assert(s);
75         assert(prefix);
76
77         sl = strlen(s);
78         pl = strlen(prefix);
79
80         if (sl < pl)
81                 return false;
82
83         return memcmp(s, prefix, pl) == 0;
84 }
85
86 int close_nointr(int fd) {
87         assert(fd >= 0);
88
89         for (;;) {
90                 int r;
91
92                 if ((r = close(fd)) >= 0)
93                         return r;
94
95                 if (errno != EINTR)
96                         return r;
97         }
98 }
99
100 void close_nointr_nofail(int fd) {
101
102         /* like close_nointr() but cannot fail, and guarantees errno
103          * is unchanged */
104
105         assert_se(close_nointr(fd) == 0);
106 }
107
108 int parse_boolean(const char *v) {
109         assert(v);
110
111         if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
112                 return 1;
113         else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
114                 return 0;
115
116         return -EINVAL;
117 }
118
119 int safe_atou(const char *s, unsigned *ret_u) {
120         char *x = NULL;
121         unsigned long l;
122
123         assert(s);
124         assert(ret_u);
125
126         errno = 0;
127         l = strtoul(s, &x, 0);
128
129         if (!x || *x || errno)
130                 return errno ? -errno : -EINVAL;
131
132         if ((unsigned long) (unsigned) l != l)
133                 return -ERANGE;
134
135         *ret_u = (unsigned) l;
136         return 0;
137 }
138
139 int safe_atoi(const char *s, int *ret_i) {
140         char *x = NULL;
141         long l;
142
143         assert(s);
144         assert(ret_i);
145
146         errno = 0;
147         l = strtol(s, &x, 0);
148
149         if (!x || *x || errno)
150                 return errno ? -errno : -EINVAL;
151
152         if ((long) (int) l != l)
153                 return -ERANGE;
154
155         *ret_i = (int) l;
156         return 0;
157 }
158
159 int safe_atolu(const char *s, long unsigned *ret_lu) {
160         char *x = NULL;
161         unsigned long l;
162
163         assert(s);
164         assert(ret_lu);
165
166         errno = 0;
167         l = strtoul(s, &x, 0);
168
169         if (!x || *x || errno)
170                 return errno ? -errno : -EINVAL;
171
172         *ret_lu = l;
173         return 0;
174 }
175
176 int safe_atoli(const char *s, long int *ret_li) {
177         char *x = NULL;
178         long l;
179
180         assert(s);
181         assert(ret_li);
182
183         errno = 0;
184         l = strtol(s, &x, 0);
185
186         if (!x || *x || errno)
187                 return errno ? -errno : -EINVAL;
188
189         *ret_li = l;
190         return 0;
191 }
192
193 int safe_atollu(const char *s, long long unsigned *ret_llu) {
194         char *x = NULL;
195         unsigned long long l;
196
197         assert(s);
198         assert(ret_llu);
199
200         errno = 0;
201         l = strtoull(s, &x, 0);
202
203         if (!x || *x || errno)
204                 return errno ? -errno : -EINVAL;
205
206         *ret_llu = l;
207         return 0;
208 }
209
210 int safe_atolli(const char *s, long long int *ret_lli) {
211         char *x = NULL;
212         long long l;
213
214         assert(s);
215         assert(ret_lli);
216
217         errno = 0;
218         l = strtoll(s, &x, 0);
219
220         if (!x || *x || errno)
221                 return errno ? -errno : -EINVAL;
222
223         *ret_lli = l;
224         return 0;
225 }
226
227 /* Split a string into words. */
228 char *split_spaces(const char *c, size_t *l, char **state) {
229         char *current;
230
231         current = *state ? *state : (char*) c;
232
233         if (!*current || *c == 0)
234                 return NULL;
235
236         current += strspn(current, WHITESPACE);
237         *l = strcspn(current, WHITESPACE);
238         *state = current+*l;
239
240         return (char*) current;
241 }
242
243 /* Split a string into words, but consider strings enclosed in '' and
244  * "" as words even if they include spaces. */
245 char *split_quoted(const char *c, size_t *l, char **state) {
246         char *current;
247
248         current = *state ? *state : (char*) c;
249
250         if (!*current || *c == 0)
251                 return NULL;
252
253         current += strspn(current, WHITESPACE);
254
255         if (*current == '\'') {
256                 current ++;
257                 *l = strcspn(current, "'");
258                 *state = current+*l;
259
260                 if (**state == '\'')
261                         (*state)++;
262         } else if (*current == '\"') {
263                 current ++;
264                 *l = strcspn(current, "\"");
265                 *state = current+*l;
266
267                 if (**state == '\"')
268                         (*state)++;
269         } else {
270                 *l = strcspn(current, WHITESPACE);
271                 *state = current+*l;
272         }
273
274         /* FIXME: Cannot deal with strings that have spaces AND ticks
275          * in them */
276
277         return (char*) current;
278 }
279
280 const char *sigchld_code(int code) {
281
282         if (code == CLD_EXITED)
283                 return "exited";
284         else if (code == CLD_KILLED)
285                 return "killed";
286         else if (code == CLD_DUMPED)
287                 return "dumped";
288         else if (code == CLD_TRAPPED)
289                 return "trapped";
290         else if (code == CLD_STOPPED)
291                 return "stopped";
292         else if (code == CLD_CONTINUED)
293                 return "continued";
294
295         return "unknown";
296 }
297
298 int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
299         int r;
300         FILE *f;
301         char fn[132], line[256], *p;
302         long long unsigned ppid;
303
304         assert(pid >= 0);
305         assert(_ppid);
306
307         assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%llu/stat", (unsigned long long) pid) < (int) (sizeof(fn)-1));
308         fn[sizeof(fn)-1] = 0;
309
310         if (!(f = fopen(fn, "r")))
311                 return -errno;
312
313         if (!(fgets(line, sizeof(line), f))) {
314                 r = -errno;
315                 fclose(f);
316                 return r;
317         }
318
319         fclose(f);
320
321         /* Let's skip the pid and comm fields. The latter is enclosed
322          * in () but does not escape any () in its value, so let's
323          * skip over it manually */
324
325         if (!(p = strrchr(line, ')')))
326                 return -EIO;
327
328         p++;
329
330         if (sscanf(p, " "
331                    "%*c "  /* state */
332                    "%llu ", /* ppid */
333                    &ppid) != 1)
334                 return -EIO;
335
336         if ((long long unsigned) (pid_t) ppid != ppid)
337                 return -ERANGE;
338
339         *_ppid = (pid_t) ppid;
340
341         return 0;
342 }
343
344 int write_one_line_file(const char *fn, const char *line) {
345         FILE *f;
346         int r;
347
348         assert(fn);
349         assert(line);
350
351         if (!(f = fopen(fn, "we")))
352                 return -errno;
353
354         if (fputs(line, f) < 0) {
355                 r = -errno;
356                 goto finish;
357         }
358
359         r = 0;
360 finish:
361         fclose(f);
362         return r;
363 }
364
365 int read_one_line_file(const char *fn, char **line) {
366         FILE *f;
367         int r;
368         char t[64], *c;
369
370         assert(fn);
371         assert(line);
372
373         if (!(f = fopen(fn, "re")))
374                 return -errno;
375
376         if (!(fgets(t, sizeof(t), f))) {
377                 r = -errno;
378                 goto finish;
379         }
380
381         if (!(c = strdup(t))) {
382                 r = -ENOMEM;
383                 goto finish;
384         }
385
386         *line = c;
387         r = 0;
388
389 finish:
390         fclose(f);
391         return r;
392 }
393
394 char *strappend(const char *s, const char *suffix) {
395         size_t a, b;
396         char *r;
397
398         assert(s);
399         assert(suffix);
400
401         a = strlen(s);
402         b = strlen(suffix);
403
404         if (!(r = new(char, a+b+1)))
405                 return NULL;
406
407         memcpy(r, s, a);
408         memcpy(r+a, suffix, b);
409         r[a+b] = 0;
410
411         return r;
412 }
413
414 int readlink_malloc(const char *p, char **r) {
415         size_t l = 100;
416
417         assert(p);
418         assert(r);
419
420         for (;;) {
421                 char *c;
422                 ssize_t n;
423
424                 if (!(c = new(char, l)))
425                         return -ENOMEM;
426
427                 if ((n = readlink(p, c, l-1)) < 0) {
428                         int ret = -errno;
429                         free(c);
430                         return ret;
431                 }
432
433                 if ((size_t) n < l-1) {
434                         c[n] = 0;
435                         *r = c;
436                         return 0;
437                 }
438
439                 free(c);
440                 l *= 2;
441         }
442 }
443
444 char *file_name_from_path(const char *p) {
445         char *r;
446
447         assert(p);
448
449         if ((r = strrchr(p, '/')))
450                 return r + 1;
451
452         return (char*) p;
453 }
454
455 bool path_is_absolute(const char *p) {
456         assert(p);
457
458         return p[0] == '/';
459 }
460
461 bool is_path(const char *p) {
462
463         return !!strchr(p, '/');
464 }
465
466 char *path_make_absolute(const char *p, const char *prefix) {
467         char *r;
468
469         assert(p);
470
471         if (path_is_absolute(p) || !prefix)
472                 return strdup(p);
473
474         if (asprintf(&r, "%s/%s", prefix, p) < 0)
475                 return NULL;
476
477         return r;
478 }
479
480 int reset_all_signal_handlers(void) {
481         int sig;
482
483         for (sig = 1; sig < _NSIG; sig++) {
484                 struct sigaction sa;
485
486                 if (sig == SIGKILL || sig == SIGSTOP)
487                         continue;
488
489                 zero(sa);
490                 sa.sa_handler = SIG_DFL;
491                 sa.sa_flags = SA_RESTART;
492
493                 /* On Linux the first two RT signals are reserved by
494                  * glibc, and sigaction() will return EINVAL for them. */
495                 if ((sigaction(sig, &sa, NULL) < 0))
496                         if (errno != EINVAL)
497                                 return -errno;
498         }
499
500     return 0;
501 }
502
503 char *strstrip(char *s) {
504         char *e, *l = NULL;
505
506         /* Drops trailing whitespace. Modifies the string in
507          * place. Returns pointer to first non-space character */
508
509         s += strspn(s, WHITESPACE);
510
511         for (e = s; *e; e++)
512                 if (!strchr(WHITESPACE, *e))
513                         l = e;
514
515         if (l)
516                 *(l+1) = 0;
517         else
518                 *s = 0;
519
520         return s;
521
522 }
523
524 char *file_in_same_dir(const char *path, const char *filename) {
525         char *e, *r;
526         size_t k;
527
528         assert(path);
529         assert(filename);
530
531         /* This removes the last component of path and appends
532          * filename, unless the latter is absolute anyway or the
533          * former isn't */
534
535         if (path_is_absolute(filename))
536                 return strdup(filename);
537
538         if (!(e = strrchr(path, '/')))
539                 return strdup(filename);
540
541         k = strlen(filename);
542         if (!(r = new(char, e-path+1+k+1)))
543                 return NULL;
544
545         memcpy(r, path, e-path+1);
546         memcpy(r+(e-path)+1, filename, k+1);
547
548         return r;
549 }
550
551 char hexchar(int x) {
552         static const char table[16] = "0123456789abcdef";
553
554         return table[x & 15];
555 }
556
557 int unhexchar(char c) {
558
559         if (c >= '0' && c <= '9')
560                 return c - '0';
561
562         if (c >= 'a' && c <= 'f')
563                 return c - 'a';
564
565         if (c >= 'A' && c <= 'F')
566                 return c - 'A';
567
568         return -1;
569 }
570
571 char octchar(int x) {
572         return '0' + (x & 7);
573 }
574
575 int unoctchar(char c) {
576
577         if (c >= '0' && c <= '7')
578                 return c - '0';
579
580         return -1;
581 }
582
583 char *cescape(const char *s) {
584         char *r, *t;
585         const char *f;
586
587         assert(s);
588
589         /* Does C style string escaping. */
590
591         if (!(r = new(char, strlen(s)*4 + 1)))
592                 return NULL;
593
594         for (f = s, t = r; *f; f++)
595
596                 switch (*f) {
597
598                 case '\a':
599                         *(t++) = '\\';
600                         *(t++) = 'a';
601                         break;
602                 case '\b':
603                         *(t++) = '\\';
604                         *(t++) = 'b';
605                         break;
606                 case '\f':
607                         *(t++) = '\\';
608                         *(t++) = 'f';
609                         break;
610                 case '\n':
611                         *(t++) = '\\';
612                         *(t++) = 'n';
613                         break;
614                 case '\r':
615                         *(t++) = '\\';
616                         *(t++) = 'r';
617                         break;
618                 case '\t':
619                         *(t++) = '\\';
620                         *(t++) = 't';
621                         break;
622                 case '\v':
623                         *(t++) = '\\';
624                         *(t++) = 'v';
625                         break;
626                 case '\\':
627                         *(t++) = '\\';
628                         *(t++) = '\\';
629                         break;
630                 case '"':
631                         *(t++) = '\\';
632                         *(t++) = '"';
633                         break;
634                 case '\'':
635                         *(t++) = '\\';
636                         *(t++) = '\'';
637                         break;
638
639                 default:
640                         /* For special chars we prefer octal over
641                          * hexadecimal encoding, simply because glib's
642                          * g_strescape() does the same */
643                         if ((*f < ' ') || (*f >= 127)) {
644                                 *(t++) = '\\';
645                                 *(t++) = octchar((unsigned char) *f >> 6);
646                                 *(t++) = octchar((unsigned char) *f >> 3);
647                                 *(t++) = octchar((unsigned char) *f);
648                         } else
649                                 *(t++) = *f;
650                         break;
651                 }
652
653         *t = 0;
654
655         return r;
656 }
657
658 char *cunescape(const char *s) {
659         char *r, *t;
660         const char *f;
661
662         assert(s);
663
664         /* Undoes C style string escaping */
665
666         if (!(r = new(char, strlen(s)+1)))
667                 return r;
668
669         for (f = s, t = r; *f; f++) {
670
671                 if (*f != '\\') {
672                         *(t++) = *f;
673                         continue;
674                 }
675
676                 f++;
677
678                 switch (*f) {
679
680                 case 'a':
681                         *(t++) = '\a';
682                         break;
683                 case 'b':
684                         *(t++) = '\b';
685                         break;
686                 case 'f':
687                         *(t++) = '\f';
688                         break;
689                 case 'n':
690                         *(t++) = '\n';
691                         break;
692                 case 'r':
693                         *(t++) = '\r';
694                         break;
695                 case 't':
696                         *(t++) = '\t';
697                         break;
698                 case 'v':
699                         *(t++) = '\v';
700                         break;
701                 case '\\':
702                         *(t++) = '\\';
703                         break;
704                 case '"':
705                         *(t++) = '"';
706                         break;
707                 case '\'':
708                         *(t++) = '\'';
709                         break;
710
711                 case 'x': {
712                         /* hexadecimal encoding */
713                         int a, b;
714
715                         if ((a = unhexchar(f[1])) < 0 ||
716                             (b = unhexchar(f[2])) < 0) {
717                                 /* Invalid escape code, let's take it literal then */
718                                 *(t++) = '\\';
719                                 *(t++) = 'x';
720                         } else {
721                                 *(t++) = (char) ((a << 4) | b);
722                                 f += 2;
723                         }
724
725                         break;
726                 }
727
728                 case '0':
729                 case '1':
730                 case '2':
731                 case '3':
732                 case '4':
733                 case '5':
734                 case '6':
735                 case '7': {
736                         /* octal encoding */
737                         int a, b, c;
738
739                         if ((a = unoctchar(f[0])) < 0 ||
740                             (b = unoctchar(f[1])) < 0 ||
741                             (c = unoctchar(f[2])) < 0) {
742                                 /* Invalid escape code, let's take it literal then */
743                                 *(t++) = '\\';
744                                 *(t++) = f[0];
745                         } else {
746                                 *(t++) = (char) ((a << 6) | (b << 3) | c);
747                                 f += 2;
748                         }
749
750                         break;
751                 }
752
753                 case 0:
754                         /* premature end of string.*/
755                         *(t++) = '\\';
756                         goto finish;
757
758                 default:
759                         /* Invalid escape code, let's take it literal then */
760                         *(t++) = '\\';
761                         *(t++) = 'f';
762                         break;
763                 }
764         }
765
766 finish:
767         *t = 0;
768         return r;
769 }
770
771
772 char *xescape(const char *s, const char *bad) {
773         char *r, *t;
774         const char *f;
775
776         /* Escapes all chars in bad, in addition to \ and all special
777          * chars, in \xFF style escaping. May be reversed with
778          * cunescape. */
779
780         if (!(r = new(char, strlen(s)*4+1)))
781                 return NULL;
782
783         for (f = s, t = r; *f; f++) {
784
785                 if (*f < ' ' || *f >= 127 ||
786                     *f == '\\' || strchr(bad, *f)) {
787                         *(t++) = '\\';
788                         *(t++) = 'x';
789                         *(t++) = hexchar(*f >> 4);
790                         *(t++) = hexchar(*f);
791                 } else
792                         *(t++) = *f;
793         }
794
795         *t = 0;
796
797         return r;
798 }
799
800 char *path_kill_slashes(char *path) {
801         char *f, *t;
802         bool slash = false;
803
804         /* Removes redundant inner and trailing slashes. Modifies the
805          * passed string in-place.
806          *
807          * ///foo///bar/ becomes /foo/bar
808          */
809
810         for (f = path, t = path; *f; f++) {
811
812                 if (*f == '/') {
813                         slash = true;
814                         continue;
815                 }
816
817                 if (slash) {
818                         slash = false;
819                         *(t++) = '/';
820                 }
821
822                 *(t++) = *f;
823         }
824
825         /* Special rule, if we are talking of the root directory, a
826         trailing slash is good */
827
828         if (t == path && slash)
829                 *(t++) = '/';
830
831         *t = 0;
832         return path;
833 }
834
835 bool path_startswith(const char *path, const char *prefix) {
836         assert(path);
837         assert(prefix);
838
839         if ((path[0] == '/') != (prefix[0] == '/'))
840                 return false;
841
842         for (;;) {
843                 size_t a, b;
844
845                 path += strspn(path, "/");
846                 prefix += strspn(prefix, "/");
847
848                 if (*prefix == 0)
849                         return true;
850
851                 if (*path == 0)
852                         return false;
853
854                 a = strcspn(path, "/");
855                 b = strcspn(prefix, "/");
856
857                 if (a != b)
858                         return false;
859
860                 if (memcmp(path, prefix, a) != 0)
861                         return false;
862
863                 path += a;
864                 prefix += b;
865         }
866 }
867
868 char *ascii_strlower(char *path) {
869         char *p;
870
871         assert(path);
872
873         for (p = path; *p; p++)
874                 if (*p >= 'A' && *p <= 'Z')
875                         *p = *p - 'A' + 'a';
876
877         return p;
878 }