chiark / gitweb /
basic: turn off stdio locking for a couple of helper calls
[elogind.git] / src / basic / process-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2010 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <linux/oom.h>
25 #include <sched.h>
26 #include <signal.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdio_ext.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/mman.h>
33 #include <sys/personality.h>
34 #include <sys/prctl.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <syslog.h>
38 #include <unistd.h>
39 #if HAVE_VALGRIND_VALGRIND_H
40 #include <valgrind/valgrind.h>
41 #endif
42
43 #include "alloc-util.h"
44 //#include "architecture.h"
45 #include "escape.h"
46 #include "fd-util.h"
47 #include "fileio.h"
48 #include "fs-util.h"
49 //#include "ioprio.h"
50 #include "log.h"
51 #include "macro.h"
52 #include "missing.h"
53 #include "process-util.h"
54 //#include "raw-clone.h"
55 #include "signal-util.h"
56 //#include "stat-util.h"
57 #include "string-table.h"
58 #include "string-util.h"
59 #include "user-util.h"
60 #include "util.h"
61
62 int get_process_state(pid_t pid) {
63         const char *p;
64         char state;
65         int r;
66         _cleanup_free_ char *line = NULL;
67
68         assert(pid >= 0);
69
70         p = procfs_file_alloca(pid, "stat");
71
72         r = read_one_line_file(p, &line);
73         if (r == -ENOENT)
74                 return -ESRCH;
75         if (r < 0)
76                 return r;
77
78         p = strrchr(line, ')');
79         if (!p)
80                 return -EIO;
81
82         p++;
83
84         if (sscanf(p, " %c", &state) != 1)
85                 return -EIO;
86
87         return (unsigned char) state;
88 }
89
90 int get_process_comm(pid_t pid, char **name) {
91         const char *p;
92         int r;
93
94         assert(name);
95         assert(pid >= 0);
96
97         p = procfs_file_alloca(pid, "comm");
98
99         r = read_one_line_file(p, name);
100         if (r == -ENOENT)
101                 return -ESRCH;
102
103         return r;
104 }
105
106 int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
107         _cleanup_fclose_ FILE *f = NULL;
108         bool space = false;
109         char *k, *ans = NULL;
110         const char *p;
111         int c;
112
113         assert(line);
114         assert(pid >= 0);
115
116         /* Retrieves a process' command line. Replaces unprintable characters while doing so by whitespace (coalescing
117          * multiple sequential ones into one). If max_length is != 0 will return a string of the specified size at most
118          * (the trailing NUL byte does count towards the length here!), abbreviated with a "..." ellipsis. If
119          * comm_fallback is true and the process has no command line set (the case for kernel threads), or has a
120          * command line that resolves to the empty string will return the "comm" name of the process instead.
121          *
122          * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
123          * comm_fallback is false). Returns 0 and sets *line otherwise. */
124
125         p = procfs_file_alloca(pid, "cmdline");
126
127         f = fopen(p, "re");
128         if (!f) {
129                 if (errno == ENOENT)
130                         return -ESRCH;
131                 return -errno;
132         }
133
134         (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
135
136         if (max_length == 1) {
137
138                 /* If there's only room for one byte, return the empty string */
139                 ans = new0(char, 1);
140                 if (!ans)
141                         return -ENOMEM;
142
143                 *line = ans;
144                 return 0;
145
146         } else if (max_length == 0) {
147                 size_t len = 0, allocated = 0;
148
149                 while ((c = getc(f)) != EOF) {
150
151                         if (!GREEDY_REALLOC(ans, allocated, len+3)) {
152                                 free(ans);
153                                 return -ENOMEM;
154                         }
155
156                         if (isprint(c)) {
157                                 if (space) {
158                                         ans[len++] = ' ';
159                                         space = false;
160                                 }
161
162                                 ans[len++] = c;
163                         } else if (len > 0)
164                                 space = true;
165                }
166
167                 if (len > 0)
168                         ans[len] = '\0';
169                 else
170                         ans = mfree(ans);
171
172         } else {
173                 bool dotdotdot = false;
174                 size_t left;
175
176                 ans = new(char, max_length);
177                 if (!ans)
178                         return -ENOMEM;
179
180                 k = ans;
181                 left = max_length;
182                 while ((c = getc(f)) != EOF) {
183
184                         if (isprint(c)) {
185
186                                 if (space) {
187                                         if (left <= 2) {
188                                                 dotdotdot = true;
189                                                 break;
190                                         }
191
192                                         *(k++) = ' ';
193                                         left--;
194                                         space = false;
195                                 }
196
197                                 if (left <= 1) {
198                                         dotdotdot = true;
199                                         break;
200                                 }
201
202                                 *(k++) = (char) c;
203                                 left--;
204                         } else if (k > ans)
205                                 space = true;
206                 }
207
208                 if (dotdotdot) {
209                         if (max_length <= 4) {
210                                 k = ans;
211                                 left = max_length;
212                         } else {
213                                 k = ans + max_length - 4;
214                                 left = 4;
215
216                                 /* Eat up final spaces */
217                                 while (k > ans && isspace(k[-1])) {
218                                         k--;
219                                         left++;
220                                 }
221                         }
222
223                         strncpy(k, "...", left-1);
224                         k[left-1] = 0;
225                 } else
226                         *k = 0;
227         }
228
229         /* Kernel threads have no argv[] */
230         if (isempty(ans)) {
231                 _cleanup_free_ char *t = NULL;
232                 int h;
233
234                 free(ans);
235
236                 if (!comm_fallback)
237                         return -ENOENT;
238
239                 h = get_process_comm(pid, &t);
240                 if (h < 0)
241                         return h;
242
243                 if (max_length == 0)
244                         ans = strjoin("[", t, "]");
245                 else {
246                         size_t l;
247
248                         l = strlen(t);
249
250                         if (l + 3 <= max_length)
251                                 ans = strjoin("[", t, "]");
252                         else if (max_length <= 6) {
253
254                                 ans = new(char, max_length);
255                                 if (!ans)
256                                         return -ENOMEM;
257
258                                 memcpy(ans, "[...]", max_length-1);
259                                 ans[max_length-1] = 0;
260                         } else {
261                                 char *e;
262
263                                 t[max_length - 6] = 0;
264
265                                 /* Chop off final spaces */
266                                 e = strchr(t, 0);
267                                 while (e > t && isspace(e[-1]))
268                                         e--;
269                                 *e = 0;
270
271                                 ans = strjoin("[", t, "...]");
272                         }
273                 }
274                 if (!ans)
275                         return -ENOMEM;
276         }
277
278         *line = ans;
279         return 0;
280 }
281
282 #if 0 /// UNNEEDED by elogind
283 int rename_process(const char name[]) {
284         static size_t mm_size = 0;
285         static char *mm = NULL;
286         bool truncated = false;
287         size_t l;
288
289         /* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
290          * internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
291          * many cases one of 10 (i.e. length of "/sbin/init") — however if we have CAP_SYS_RESOURCES it is unbounded;
292          * to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
293          * truncated.
294          *
295          * Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
296
297         if (isempty(name))
298                 return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
299
300         l = strlen(name);
301
302         /* First step, change the comm field. */
303         (void) prctl(PR_SET_NAME, name);
304         if (l > 15) /* Linux process names can be 15 chars at max */
305                 truncated = true;
306
307         /* Second step, change glibc's ID of the process name. */
308         if (program_invocation_name) {
309                 size_t k;
310
311                 k = strlen(program_invocation_name);
312                 strncpy(program_invocation_name, name, k);
313                 if (l > k)
314                         truncated = true;
315         }
316
317         /* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
318          * has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
319          * the end. This is the best option for changing /proc/self/cmdline. */
320
321         /* Let's not bother with this if we don't have euid == 0. Strictly speaking we should check for the
322          * CAP_SYS_RESOURCE capability which is independent of the euid. In our own code the capability generally is
323          * present only for euid == 0, hence let's use this as quick bypass check, to avoid calling mmap() if
324          * PR_SET_MM_ARG_{START,END} fails with EPERM later on anyway. After all geteuid() is dead cheap to call, but
325          * mmap() is not. */
326         if (geteuid() != 0)
327                 log_debug("Skipping PR_SET_MM, as we don't have privileges.");
328         else if (mm_size < l+1) {
329                 size_t nn_size;
330                 char *nn;
331
332                 nn_size = PAGE_ALIGN(l+1);
333                 nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
334                 if (nn == MAP_FAILED) {
335                         log_debug_errno(errno, "mmap() failed: %m");
336                         goto use_saved_argv;
337                 }
338
339                 strncpy(nn, name, nn_size);
340
341                 /* Now, let's tell the kernel about this new memory */
342                 if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
343                         log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m");
344                         (void) munmap(nn, nn_size);
345                         goto use_saved_argv;
346                 }
347
348                 /* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's
349                  * pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */
350                 if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
351                         log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
352
353                 if (mm)
354                         (void) munmap(mm, mm_size);
355
356                 mm = nn;
357                 mm_size = nn_size;
358         } else {
359                 strncpy(mm, name, mm_size);
360
361                 /* Update the end pointer, continuing regardless of any failure. */
362                 if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) mm + l + 1, 0, 0) < 0)
363                         log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
364         }
365
366 use_saved_argv:
367         /* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
368          * it still looks here */
369
370         if (saved_argc > 0) {
371                 int i;
372
373                 if (saved_argv[0]) {
374                         size_t k;
375
376                         k = strlen(saved_argv[0]);
377                         strncpy(saved_argv[0], name, k);
378                         if (l > k)
379                                 truncated = true;
380                 }
381
382                 for (i = 1; i < saved_argc; i++) {
383                         if (!saved_argv[i])
384                                 break;
385
386                         memzero(saved_argv[i], strlen(saved_argv[i]));
387                 }
388         }
389
390         return !truncated;
391 }
392 #endif // 0
393
394 int is_kernel_thread(pid_t pid) {
395         const char *p;
396         size_t count;
397         char c;
398         bool eof;
399         FILE *f;
400
401         if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
402                 return 0;
403
404         assert(pid > 1);
405
406         p = procfs_file_alloca(pid, "cmdline");
407         f = fopen(p, "re");
408         if (!f) {
409                 if (errno == ENOENT)
410                         return -ESRCH;
411                 return -errno;
412         }
413
414         (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
415
416         count = fread(&c, 1, 1, f);
417         eof = feof(f);
418         fclose(f);
419
420         /* Kernel threads have an empty cmdline */
421
422         if (count <= 0)
423                 return eof ? 1 : -errno;
424
425         return 0;
426 }
427
428 #if 0 /// UNNEEDED by elogind
429 int get_process_capeff(pid_t pid, char **capeff) {
430         const char *p;
431         int r;
432
433         assert(capeff);
434         assert(pid >= 0);
435
436         p = procfs_file_alloca(pid, "status");
437
438         r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
439         if (r == -ENOENT)
440                 return -ESRCH;
441
442         return r;
443 }
444 #endif // 0
445
446 static int get_process_link_contents(const char *proc_file, char **name) {
447         int r;
448
449         assert(proc_file);
450         assert(name);
451
452         r = readlink_malloc(proc_file, name);
453         if (r == -ENOENT)
454                 return -ESRCH;
455         if (r < 0)
456                 return r;
457
458         return 0;
459 }
460
461 int get_process_exe(pid_t pid, char **name) {
462         const char *p;
463         char *d;
464         int r;
465
466         assert(pid >= 0);
467
468         p = procfs_file_alloca(pid, "exe");
469         r = get_process_link_contents(p, name);
470         if (r < 0)
471                 return r;
472
473         d = endswith(*name, " (deleted)");
474         if (d)
475                 *d = '\0';
476
477         return 0;
478 }
479
480 #if 0 /// UNNEEDED by elogind
481 static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
482         _cleanup_fclose_ FILE *f = NULL;
483         char line[LINE_MAX];
484         const char *p;
485
486         assert(field);
487         assert(uid);
488
489         if (pid < 0)
490                 return -EINVAL;
491
492         p = procfs_file_alloca(pid, "status");
493         f = fopen(p, "re");
494         if (!f) {
495                 if (errno == ENOENT)
496                         return -ESRCH;
497                 return -errno;
498         }
499
500         (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
501
502         FOREACH_LINE(line, f, return -errno) {
503                 char *l;
504
505                 l = strstrip(line);
506
507                 if (startswith(l, field)) {
508                         l += strlen(field);
509                         l += strspn(l, WHITESPACE);
510
511                         l[strcspn(l, WHITESPACE)] = 0;
512
513                         return parse_uid(l, uid);
514                 }
515         }
516
517         return -EIO;
518 }
519
520 int get_process_uid(pid_t pid, uid_t *uid) {
521
522         if (pid == 0 || pid == getpid_cached()) {
523                 *uid = getuid();
524                 return 0;
525         }
526
527         return get_process_id(pid, "Uid:", uid);
528 }
529
530 int get_process_gid(pid_t pid, gid_t *gid) {
531
532         if (pid == 0 || pid == getpid_cached()) {
533                 *gid = getgid();
534                 return 0;
535         }
536
537         assert_cc(sizeof(uid_t) == sizeof(gid_t));
538         return get_process_id(pid, "Gid:", gid);
539 }
540
541 int get_process_cwd(pid_t pid, char **cwd) {
542         const char *p;
543
544         assert(pid >= 0);
545
546         p = procfs_file_alloca(pid, "cwd");
547
548         return get_process_link_contents(p, cwd);
549 }
550
551 int get_process_root(pid_t pid, char **root) {
552         const char *p;
553
554         assert(pid >= 0);
555
556         p = procfs_file_alloca(pid, "root");
557
558         return get_process_link_contents(p, root);
559 }
560
561 int get_process_environ(pid_t pid, char **env) {
562         _cleanup_fclose_ FILE *f = NULL;
563         _cleanup_free_ char *outcome = NULL;
564         int c;
565         const char *p;
566         size_t allocated = 0, sz = 0;
567
568         assert(pid >= 0);
569         assert(env);
570
571         p = procfs_file_alloca(pid, "environ");
572
573         f = fopen(p, "re");
574         if (!f) {
575                 if (errno == ENOENT)
576                         return -ESRCH;
577                 return -errno;
578         }
579
580         (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
581
582         while ((c = fgetc(f)) != EOF) {
583                 if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
584                         return -ENOMEM;
585
586                 if (c == '\0')
587                         outcome[sz++] = '\n';
588                 else
589                         sz += cescape_char(c, outcome + sz);
590         }
591
592         if (!outcome) {
593                 outcome = strdup("");
594                 if (!outcome)
595                         return -ENOMEM;
596         } else
597                 outcome[sz] = '\0';
598
599         *env = outcome;
600         outcome = NULL;
601
602         return 0;
603 }
604
605 int get_process_ppid(pid_t pid, pid_t *_ppid) {
606         int r;
607         _cleanup_free_ char *line = NULL;
608         long unsigned ppid;
609         const char *p;
610
611         assert(pid >= 0);
612         assert(_ppid);
613
614         if (pid == 0 || pid == getpid_cached()) {
615                 *_ppid = getppid();
616                 return 0;
617         }
618
619         p = procfs_file_alloca(pid, "stat");
620         r = read_one_line_file(p, &line);
621         if (r == -ENOENT)
622                 return -ESRCH;
623         if (r < 0)
624                 return r;
625
626         /* Let's skip the pid and comm fields. The latter is enclosed
627          * in () but does not escape any () in its value, so let's
628          * skip over it manually */
629
630         p = strrchr(line, ')');
631         if (!p)
632                 return -EIO;
633
634         p++;
635
636         if (sscanf(p, " "
637                    "%*c "  /* state */
638                    "%lu ", /* ppid */
639                    &ppid) != 1)
640                 return -EIO;
641
642         if ((long unsigned) (pid_t) ppid != ppid)
643                 return -ERANGE;
644
645         *_ppid = (pid_t) ppid;
646
647         return 0;
648 }
649 #endif // 0
650
651 int wait_for_terminate(pid_t pid, siginfo_t *status) {
652         siginfo_t dummy;
653
654         assert(pid >= 1);
655
656         if (!status)
657                 status = &dummy;
658
659         for (;;) {
660                 zero(*status);
661
662                 if (waitid(P_PID, pid, status, WEXITED) < 0) {
663
664                         if (errno == EINTR)
665                                 continue;
666
667                         return negative_errno();
668                 }
669
670                 return 0;
671         }
672 }
673
674 /*
675  * Return values:
676  * < 0 : wait_for_terminate() failed to get the state of the
677  *       process, the process was terminated by a signal, or
678  *       failed for an unknown reason.
679  * >=0 : The process terminated normally, and its exit code is
680  *       returned.
681  *
682  * That is, success is indicated by a return value of zero, and an
683  * error is indicated by a non-zero value.
684  *
685  * A warning is emitted if the process terminates abnormally,
686  * and also if it returns non-zero unless check_exit_code is true.
687  */
688 int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
689         int r;
690         siginfo_t status;
691
692         assert(name);
693         assert(pid > 1);
694
695         r = wait_for_terminate(pid, &status);
696         if (r < 0)
697                 return log_warning_errno(r, "Failed to wait for %s: %m", name);
698
699         if (status.si_code == CLD_EXITED) {
700                 if (status.si_status != 0)
701                         log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
702                                  "%s failed with error code %i.", name, status.si_status);
703                 else
704                         log_debug("%s succeeded.", name);
705
706                 return status.si_status;
707         } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {
708
709                 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
710                 return -EPROTO;
711         }
712
713         log_warning("%s failed due to unknown reason.", name);
714         return -EPROTO;
715 }
716
717 #if 0 /// UNNEEDED by elogind
718 void sigkill_wait(pid_t pid) {
719         assert(pid > 1);
720
721         if (kill(pid, SIGKILL) > 0)
722                 (void) wait_for_terminate(pid, NULL);
723 }
724
725 void sigkill_waitp(pid_t *pid) {
726         if (!pid)
727                 return;
728         if (*pid <= 1)
729                 return;
730
731         sigkill_wait(*pid);
732 }
733
734 int kill_and_sigcont(pid_t pid, int sig) {
735         int r;
736
737         r = kill(pid, sig) < 0 ? -errno : 0;
738
739         /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
740          * affected by a process being suspended anyway. */
741         if (r >= 0 && !IN_SET(sig, SIGCONT, SIGKILL))
742                 (void) kill(pid, SIGCONT);
743
744         return r;
745 }
746 #endif // 0
747
748 int getenv_for_pid(pid_t pid, const char *field, char **_value) {
749         _cleanup_fclose_ FILE *f = NULL;
750         char *value = NULL;
751         int r;
752         bool done = false;
753         size_t l;
754         const char *path;
755
756         assert(pid >= 0);
757         assert(field);
758         assert(_value);
759
760         path = procfs_file_alloca(pid, "environ");
761
762         f = fopen(path, "re");
763         if (!f) {
764                 if (errno == ENOENT)
765                         return -ESRCH;
766                 return -errno;
767         }
768
769         (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
770
771         l = strlen(field);
772         r = 0;
773
774         do {
775                 char line[LINE_MAX];
776                 unsigned i;
777
778                 for (i = 0; i < sizeof(line)-1; i++) {
779                         int c;
780
781                         c = getc(f);
782                         if (_unlikely_(c == EOF)) {
783                                 done = true;
784                                 break;
785                         } else if (c == 0)
786                                 break;
787
788                         line[i] = c;
789                 }
790                 line[i] = 0;
791
792                 if (strneq(line, field, l) && line[l] == '=') {
793                         value = strdup(line + l + 1);
794                         if (!value)
795                                 return -ENOMEM;
796
797                         r = 1;
798                         break;
799                 }
800
801         } while (!done);
802
803         *_value = value;
804         return r;
805 }
806
807 bool pid_is_unwaited(pid_t pid) {
808         /* Checks whether a PID is still valid at all, including a zombie */
809
810         if (pid < 0)
811                 return false;
812
813         if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
814                 return true;
815
816         if (pid == getpid_cached())
817                 return true;
818
819         if (kill(pid, 0) >= 0)
820                 return true;
821
822         return errno != ESRCH;
823 }
824
825 bool pid_is_alive(pid_t pid) {
826         int r;
827
828         /* Checks whether a PID is still valid and not a zombie */
829
830         if (pid < 0)
831                 return false;
832
833         if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
834                 return true;
835
836         if (pid == getpid_cached())
837                 return true;
838
839         r = get_process_state(pid);
840         if (IN_SET(r, -ESRCH, 'Z'))
841                 return false;
842
843         return true;
844 }
845
846 #if 0 /// UNNEEDED by elogind
847 int pid_from_same_root_fs(pid_t pid) {
848         const char *root;
849
850         if (pid < 0)
851                 return false;
852
853         if (pid == 0 || pid == getpid_cached())
854                 return true;
855
856         root = procfs_file_alloca(pid, "root");
857
858         return files_same(root, "/proc/1/root", 0);
859 }
860 #endif // 0
861
862 bool is_main_thread(void) {
863         static thread_local int cached = 0;
864
865         if (_unlikely_(cached == 0))
866                 cached = getpid_cached() == gettid() ? 1 : -1;
867
868         return cached > 0;
869 }
870
871 #if 0 /// UNNEEDED by elogind
872 noreturn void freeze(void) {
873
874         log_close();
875
876         /* Make sure nobody waits for us on a socket anymore */
877         close_all_fds(NULL, 0);
878
879         sync();
880
881         for (;;)
882                 pause();
883 }
884
885 bool oom_score_adjust_is_valid(int oa) {
886         return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
887 }
888
889 unsigned long personality_from_string(const char *p) {
890         int architecture;
891
892         if (!p)
893                 return PERSONALITY_INVALID;
894
895         /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just
896          * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for
897          * the same register size. */
898
899         architecture = architecture_from_string(p);
900         if (architecture < 0)
901                 return PERSONALITY_INVALID;
902
903         if (architecture == native_architecture())
904                 return PER_LINUX;
905 #ifdef SECONDARY_ARCHITECTURE
906         if (architecture == SECONDARY_ARCHITECTURE)
907                 return PER_LINUX32;
908 #endif
909
910         return PERSONALITY_INVALID;
911 }
912
913 const char* personality_to_string(unsigned long p) {
914         int architecture = _ARCHITECTURE_INVALID;
915
916         if (p == PER_LINUX)
917                 architecture = native_architecture();
918 #ifdef SECONDARY_ARCHITECTURE
919         else if (p == PER_LINUX32)
920                 architecture = SECONDARY_ARCHITECTURE;
921 #endif
922
923         if (architecture < 0)
924                 return NULL;
925
926         return architecture_to_string(architecture);
927 }
928
929 int safe_personality(unsigned long p) {
930         int ret;
931
932         /* So here's the deal, personality() is weirdly defined by glibc. In some cases it returns a failure via errno,
933          * and in others as negative return value containing an errno-like value. Let's work around this: this is a
934          * wrapper that uses errno if it is set, and uses the return value otherwise. And then it sets both errno and
935          * the return value indicating the same issue, so that we are definitely on the safe side.
936          *
937          * See https://github.com/systemd/systemd/issues/6737 */
938
939         errno = 0;
940         ret = personality(p);
941         if (ret < 0) {
942                 if (errno != 0)
943                         return -errno;
944
945                 errno = -ret;
946         }
947
948         return ret;
949 }
950
951 int opinionated_personality(unsigned long *ret) {
952         int current;
953
954         /* Returns the current personality, or PERSONALITY_INVALID if we can't determine it. This function is a bit
955          * opinionated though, and ignores all the finer-grained bits and exotic personalities, only distinguishing the
956          * two most relevant personalities: PER_LINUX and PER_LINUX32. */
957
958         current = safe_personality(PERSONALITY_INVALID);
959         if (current < 0)
960                 return current;
961
962         if (((unsigned long) current & 0xffff) == PER_LINUX32)
963                 *ret = PER_LINUX32;
964         else
965                 *ret = PER_LINUX;
966
967         return 0;
968 }
969
970 void valgrind_summary_hack(void) {
971 #if HAVE_VALGRIND_VALGRIND_H
972         if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
973                 pid_t pid;
974                 pid = raw_clone(SIGCHLD);
975                 if (pid < 0)
976                         log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
977                 else if (pid == 0)
978                         exit(EXIT_SUCCESS);
979                 else {
980                         log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
981                         (void) wait_for_terminate(pid, NULL);
982                 }
983         }
984 #endif
985 }
986
987 int pid_compare_func(const void *a, const void *b) {
988         const pid_t *p = a, *q = b;
989
990         /* Suitable for usage in qsort() */
991
992         if (*p < *q)
993                 return -1;
994         if (*p > *q)
995                 return 1;
996         return 0;
997 }
998
999 int ioprio_parse_priority(const char *s, int *ret) {
1000         int i, r;
1001
1002         assert(s);
1003         assert(ret);
1004
1005         r = safe_atoi(s, &i);
1006         if (r < 0)
1007                 return r;
1008
1009         if (!ioprio_priority_is_valid(i))
1010                 return -EINVAL;
1011
1012         *ret = i;
1013         return 0;
1014 }
1015 #endif // 0
1016
1017 /* The cached PID, possible values:
1018  *
1019  *     == UNSET [0]  → cache not initialized yet
1020  *     == BUSY [-1]  → some thread is initializing it at the moment
1021  *     any other     → the cached PID
1022  */
1023
1024 #define CACHED_PID_UNSET ((pid_t) 0)
1025 #define CACHED_PID_BUSY ((pid_t) -1)
1026
1027 static pid_t cached_pid = CACHED_PID_UNSET;
1028
1029 static void reset_cached_pid(void) {
1030         /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
1031         cached_pid = CACHED_PID_UNSET;
1032 }
1033
1034 /* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc
1035  * headers. __register_atfork() is mostly equivalent to pthread_atfork(), but doesn't require us to link against
1036  * libpthread, as it is part of glibc anyway. */
1037 #ifdef __GLIBC__
1038 extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void * __dso_handle);
1039 extern void* __dso_handle __attribute__ ((__weak__));
1040 #endif // ifdef __GLIBC__
1041
1042 pid_t getpid_cached(void) {
1043         pid_t current_value;
1044
1045         /* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
1046          * system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
1047          * cached. Starting with 2.24 getpid() started to become prohibitively expensive when used for detecting when
1048          * objects were used across fork()s. With this caching the old behaviour is somewhat restored.
1049          *
1050          * https://bugzilla.redhat.com/show_bug.cgi?id=1443976
1051          * https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
1052          */
1053
1054         current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY);
1055
1056         switch (current_value) {
1057
1058         case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */
1059                 pid_t new_pid;
1060
1061                 new_pid = getpid();
1062
1063                 if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) {
1064                         /* OOM? Let's try again later */
1065                         cached_pid = CACHED_PID_UNSET;
1066                         return new_pid;
1067                 }
1068
1069                 cached_pid = new_pid;
1070                 return new_pid;
1071         }
1072
1073         case CACHED_PID_BUSY: /* Somebody else is currently initializing */
1074                 return getpid();
1075
1076         default: /* Properly initialized */
1077                 return current_value;
1078         }
1079 }
1080
1081 int must_be_root(void) {
1082
1083         if (geteuid() == 0)
1084                 return 0;
1085
1086         log_error("Need to be root.");
1087         return -EPERM;
1088 }
1089
1090 #if 0 /// UNNEEDED by elogind
1091 static const char *const ioprio_class_table[] = {
1092         [IOPRIO_CLASS_NONE] = "none",
1093         [IOPRIO_CLASS_RT] = "realtime",
1094         [IOPRIO_CLASS_BE] = "best-effort",
1095         [IOPRIO_CLASS_IDLE] = "idle"
1096 };
1097
1098 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
1099
1100 static const char *const sigchld_code_table[] = {
1101         [CLD_EXITED] = "exited",
1102         [CLD_KILLED] = "killed",
1103         [CLD_DUMPED] = "dumped",
1104         [CLD_TRAPPED] = "trapped",
1105         [CLD_STOPPED] = "stopped",
1106         [CLD_CONTINUED] = "continued",
1107 };
1108
1109 DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
1110
1111 static const char* const sched_policy_table[] = {
1112         [SCHED_OTHER] = "other",
1113         [SCHED_BATCH] = "batch",
1114         [SCHED_IDLE] = "idle",
1115         [SCHED_FIFO] = "fifo",
1116         [SCHED_RR] = "rr"
1117 };
1118
1119 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
1120 #endif // 0