]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-daemon/sd-daemon.c
fd-uitl: rename PIPE_EBADF → EBADF_PAIR, and add EBADF_TRIPLET
[thirdparty/systemd.git] / src / libsystemd / sd-daemon / sd-daemon.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <limits.h>
5 #include <mqueue.h>
6 #include <netinet/in.h>
7 #include <poll.h>
8 #include <stdarg.h>
9 #include <stddef.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <sys/stat.h>
13 #include <sys/un.h>
14 #include <unistd.h>
15
16 #include "sd-daemon.h"
17
18 #include "alloc-util.h"
19 #include "fd-util.h"
20 #include "fs-util.h"
21 #include "io-util.h"
22 #include "iovec-util.h"
23 #include "parse-util.h"
24 #include "path-util.h"
25 #include "process-util.h"
26 #include "socket-util.h"
27 #include "stat-util.h"
28 #include "strv.h"
29 #include "time-util.h"
30
31 #define SNDBUF_SIZE (8*1024*1024)
32
33 static void unsetenv_all(bool unset_environment) {
34 if (!unset_environment)
35 return;
36
37 assert_se(unsetenv("LISTEN_PID") == 0);
38 assert_se(unsetenv("LISTEN_FDS") == 0);
39 assert_se(unsetenv("LISTEN_FDNAMES") == 0);
40 }
41
42 _public_ int sd_listen_fds(int unset_environment) {
43 const char *e;
44 int n, r;
45 pid_t pid;
46
47 e = getenv("LISTEN_PID");
48 if (!e) {
49 r = 0;
50 goto finish;
51 }
52
53 r = parse_pid(e, &pid);
54 if (r < 0)
55 goto finish;
56
57 /* Is this for us? */
58 if (getpid_cached() != pid) {
59 r = 0;
60 goto finish;
61 }
62
63 e = getenv("LISTEN_FDS");
64 if (!e) {
65 r = 0;
66 goto finish;
67 }
68
69 r = safe_atoi(e, &n);
70 if (r < 0)
71 goto finish;
72
73 assert_cc(SD_LISTEN_FDS_START < INT_MAX);
74 if (n <= 0 || n > INT_MAX - SD_LISTEN_FDS_START) {
75 r = -EINVAL;
76 goto finish;
77 }
78
79 for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
80 r = fd_cloexec(fd, true);
81 if (r < 0)
82 goto finish;
83 }
84
85 r = n;
86
87 finish:
88 unsetenv_all(unset_environment);
89 return r;
90 }
91
92 _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
93 _cleanup_strv_free_ char **l = NULL;
94 bool have_names;
95 int n_names = 0, n_fds;
96 const char *e;
97 int r;
98
99 if (!names)
100 return sd_listen_fds(unset_environment);
101
102 e = getenv("LISTEN_FDNAMES");
103 if (e) {
104 n_names = strv_split_full(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
105 if (n_names < 0) {
106 unsetenv_all(unset_environment);
107 return n_names;
108 }
109
110 have_names = true;
111 } else
112 have_names = false;
113
114 n_fds = sd_listen_fds(unset_environment);
115 if (n_fds <= 0)
116 return n_fds;
117
118 if (have_names) {
119 if (n_names != n_fds)
120 return -EINVAL;
121 } else {
122 r = strv_extend_n(&l, "unknown", n_fds);
123 if (r < 0)
124 return r;
125 }
126
127 *names = TAKE_PTR(l);
128
129 return n_fds;
130 }
131
132 _public_ int sd_is_fifo(int fd, const char *path) {
133 struct stat st_fd;
134
135 assert_return(fd >= 0, -EBADF);
136
137 if (fstat(fd, &st_fd) < 0)
138 return -errno;
139
140 if (!S_ISFIFO(st_fd.st_mode))
141 return 0;
142
143 if (path) {
144 struct stat st_path;
145
146 if (stat(path, &st_path) < 0) {
147
148 if (IN_SET(errno, ENOENT, ENOTDIR))
149 return 0;
150
151 return -errno;
152 }
153
154 return stat_inode_same(&st_path, &st_fd);
155 }
156
157 return 1;
158 }
159
160 _public_ int sd_is_special(int fd, const char *path) {
161 struct stat st_fd;
162
163 assert_return(fd >= 0, -EBADF);
164
165 if (fstat(fd, &st_fd) < 0)
166 return -errno;
167
168 if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
169 return 0;
170
171 if (path) {
172 struct stat st_path;
173
174 if (stat(path, &st_path) < 0) {
175
176 if (IN_SET(errno, ENOENT, ENOTDIR))
177 return 0;
178
179 return -errno;
180 }
181
182 if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
183 return stat_inode_same(&st_path, &st_fd);
184 else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
185 return st_path.st_rdev == st_fd.st_rdev;
186 else
187 return 0;
188 }
189
190 return 1;
191 }
192
193 static int is_socket_internal(int fd, int type, int listening) {
194 struct stat st_fd;
195
196 assert_return(fd >= 0, -EBADF);
197 assert_return(type >= 0, -EINVAL);
198
199 if (fstat(fd, &st_fd) < 0)
200 return -errno;
201
202 if (!S_ISSOCK(st_fd.st_mode))
203 return 0;
204
205 if (type != 0) {
206 int other_type = 0;
207 socklen_t l = sizeof(other_type);
208
209 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
210 return -errno;
211
212 if (l != sizeof(other_type))
213 return -EINVAL;
214
215 if (other_type != type)
216 return 0;
217 }
218
219 if (listening >= 0) {
220 int accepting = 0;
221 socklen_t l = sizeof(accepting);
222
223 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
224 return -errno;
225
226 if (l != sizeof(accepting))
227 return -EINVAL;
228
229 if (!accepting != !listening)
230 return 0;
231 }
232
233 return 1;
234 }
235
236 _public_ int sd_is_socket(int fd, int family, int type, int listening) {
237 int r;
238
239 assert_return(fd >= 0, -EBADF);
240 assert_return(family >= 0, -EINVAL);
241
242 r = is_socket_internal(fd, type, listening);
243 if (r <= 0)
244 return r;
245
246 if (family > 0) {
247 union sockaddr_union sockaddr = {};
248 socklen_t l = sizeof(sockaddr);
249
250 if (getsockname(fd, &sockaddr.sa, &l) < 0)
251 return -errno;
252
253 if (l < sizeof(sa_family_t))
254 return -EINVAL;
255
256 return sockaddr.sa.sa_family == family;
257 }
258
259 return 1;
260 }
261
262 _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
263 union sockaddr_union sockaddr = {};
264 socklen_t l = sizeof(sockaddr);
265 int r;
266
267 assert_return(fd >= 0, -EBADF);
268 assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL);
269
270 r = is_socket_internal(fd, type, listening);
271 if (r <= 0)
272 return r;
273
274 if (getsockname(fd, &sockaddr.sa, &l) < 0)
275 return -errno;
276
277 if (l < sizeof(sa_family_t))
278 return -EINVAL;
279
280 if (!IN_SET(sockaddr.sa.sa_family, AF_INET, AF_INET6))
281 return 0;
282
283 if (family != 0)
284 if (sockaddr.sa.sa_family != family)
285 return 0;
286
287 if (port > 0) {
288 unsigned sa_port;
289
290 r = sockaddr_port(&sockaddr.sa, &sa_port);
291 if (r < 0)
292 return r;
293
294 return port == sa_port;
295 }
296
297 return 1;
298 }
299
300 _public_ int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening) {
301 union sockaddr_union sockaddr = {};
302 socklen_t l = sizeof(sockaddr);
303 int r;
304
305 assert_return(fd >= 0, -EBADF);
306 assert_return(addr, -EINVAL);
307 assert_return(addr_len >= sizeof(sa_family_t), -ENOBUFS);
308 assert_return(IN_SET(addr->sa_family, AF_INET, AF_INET6), -EPFNOSUPPORT);
309
310 r = is_socket_internal(fd, type, listening);
311 if (r <= 0)
312 return r;
313
314 if (getsockname(fd, &sockaddr.sa, &l) < 0)
315 return -errno;
316
317 if (l < sizeof(sa_family_t))
318 return -EINVAL;
319
320 if (sockaddr.sa.sa_family != addr->sa_family)
321 return 0;
322
323 if (sockaddr.sa.sa_family == AF_INET) {
324 const struct sockaddr_in *in = (const struct sockaddr_in *) addr;
325
326 if (l < sizeof(struct sockaddr_in) || addr_len < sizeof(struct sockaddr_in))
327 return -EINVAL;
328
329 if (in->sin_port != 0 &&
330 sockaddr.in.sin_port != in->sin_port)
331 return false;
332
333 return sockaddr.in.sin_addr.s_addr == in->sin_addr.s_addr;
334
335 } else {
336 const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) addr;
337
338 if (l < sizeof(struct sockaddr_in6) || addr_len < sizeof(struct sockaddr_in6))
339 return -EINVAL;
340
341 if (in->sin6_port != 0 &&
342 sockaddr.in6.sin6_port != in->sin6_port)
343 return false;
344
345 if (in->sin6_flowinfo != 0 &&
346 sockaddr.in6.sin6_flowinfo != in->sin6_flowinfo)
347 return false;
348
349 if (in->sin6_scope_id != 0 &&
350 sockaddr.in6.sin6_scope_id != in->sin6_scope_id)
351 return false;
352
353 return memcmp(sockaddr.in6.sin6_addr.s6_addr, in->sin6_addr.s6_addr,
354 sizeof(in->sin6_addr.s6_addr)) == 0;
355 }
356 }
357
358 _public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
359 union sockaddr_union sockaddr = {};
360 socklen_t l = sizeof(sockaddr);
361 int r;
362
363 assert_return(fd >= 0, -EBADF);
364
365 r = is_socket_internal(fd, type, listening);
366 if (r <= 0)
367 return r;
368
369 if (getsockname(fd, &sockaddr.sa, &l) < 0)
370 return -errno;
371
372 if (l < sizeof(sa_family_t))
373 return -EINVAL;
374
375 if (sockaddr.sa.sa_family != AF_UNIX)
376 return 0;
377
378 if (path) {
379 if (length == 0)
380 length = strlen(path);
381
382 if (length == 0)
383 /* Unnamed socket */
384 return l == offsetof(struct sockaddr_un, sun_path);
385
386 if (path[0])
387 /* Normal path socket */
388 return
389 (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
390 memcmp(path, sockaddr.un.sun_path, length+1) == 0;
391 else
392 /* Abstract namespace socket */
393 return
394 (l == offsetof(struct sockaddr_un, sun_path) + length) &&
395 memcmp(path, sockaddr.un.sun_path, length) == 0;
396 }
397
398 return 1;
399 }
400
401 _public_ int sd_is_mq(int fd, const char *path) {
402 struct mq_attr attr;
403
404 /* Check that the fd is valid */
405 assert_return(fcntl(fd, F_GETFD) >= 0, -errno);
406
407 if (mq_getattr(fd, &attr) < 0) {
408 if (errno == EBADF)
409 /* A non-mq fd (or an invalid one, but we ruled that out above) */
410 return 0;
411 return -errno;
412 }
413
414 if (path) {
415 _cleanup_free_ char *fpath = NULL;
416 struct stat a, b;
417
418 assert_return(path_is_absolute(path), -EINVAL);
419
420 if (fstat(fd, &a) < 0)
421 return -errno;
422
423 fpath = path_join("/dev/mqueue", path);
424 if (!fpath)
425 return -ENOMEM;
426
427 if (stat(fpath, &b) < 0)
428 return -errno;
429
430 if (!stat_inode_same(&a, &b))
431 return 0;
432 }
433
434 return 1;
435 }
436
437 static int vsock_bind_privileged_port(int fd) {
438 union sockaddr_union sa = {
439 .vm.svm_family = AF_VSOCK,
440 .vm.svm_cid = VMADDR_CID_ANY,
441 .vm.svm_port = 1023,
442 };
443 int r;
444
445 assert(fd >= 0);
446
447 do
448 r = RET_NERRNO(bind(fd, &sa.sa, sizeof(sa.vm)));
449 while (r == -EADDRINUSE && --sa.vm.svm_port > 0);
450
451 return r;
452 }
453
454 static int pid_notify_with_fds_internal(
455 pid_t pid,
456 const char *state,
457 const int *fds,
458 unsigned n_fds) {
459 SocketAddress address;
460 struct iovec iovec;
461 struct msghdr msghdr = {
462 .msg_iov = &iovec,
463 .msg_iovlen = 1,
464 .msg_name = &address.sockaddr,
465 };
466 _cleanup_close_ int fd = -EBADF;
467 struct cmsghdr *cmsg = NULL;
468 const char *e;
469 bool send_ucred;
470 ssize_t n;
471 int type, r;
472
473 if (!state)
474 return -EINVAL;
475
476 if (n_fds > 0 && !fds)
477 return -EINVAL;
478
479 e = getenv("NOTIFY_SOCKET");
480 if (!e)
481 return 0;
482
483 /* Allow AF_UNIX and AF_VSOCK, reject the rest. */
484 r = socket_address_parse_unix(&address, e);
485 if (r == -EPROTO)
486 r = socket_address_parse_vsock(&address, e);
487 if (r < 0)
488 return r;
489 msghdr.msg_namelen = address.size;
490
491 /* If we didn't get an address (which is a normal pattern when specifying VSOCK tuples) error out,
492 * we always require a specific CID. */
493 if (address.sockaddr.vm.svm_family == AF_VSOCK && address.sockaddr.vm.svm_cid == VMADDR_CID_ANY)
494 return -EINVAL;
495
496 type = address.type == 0 ? SOCK_DGRAM : address.type;
497
498 /* At the time of writing QEMU does not yet support AF_VSOCK + SOCK_DGRAM and returns
499 * ENODEV. Fallback to SOCK_SEQPACKET in that case. */
500 fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0);
501 if (fd < 0) {
502 if (!(ERRNO_IS_NOT_SUPPORTED(errno) || errno == ENODEV) || address.sockaddr.sa.sa_family != AF_VSOCK || address.type > 0)
503 return log_debug_errno(errno, "Failed to open %s notify socket to '%s': %m", socket_address_type_to_string(type), e);
504
505 type = SOCK_SEQPACKET;
506 fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0);
507 if (fd < 0 && ERRNO_IS_NOT_SUPPORTED(errno)) {
508 type = SOCK_STREAM;
509 fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0);
510 }
511 if (fd < 0)
512 return log_debug_errno(errno, "Failed to open %s socket to '%s': %m", socket_address_type_to_string(type), e);
513 }
514
515 if (address.sockaddr.sa.sa_family == AF_VSOCK) {
516 r = vsock_bind_privileged_port(fd);
517 if (r < 0 && !ERRNO_IS_PRIVILEGE(r))
518 return log_debug_errno(r, "Failed to bind socket to privileged port: %m");
519 }
520
521 if (IN_SET(type, SOCK_STREAM, SOCK_SEQPACKET)) {
522 if (connect(fd, &address.sockaddr.sa, address.size) < 0)
523 return log_debug_errno(errno, "Failed to connect socket to '%s': %m", e);
524
525 msghdr.msg_name = NULL;
526 msghdr.msg_namelen = 0;
527 }
528
529 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
530
531 iovec = IOVEC_MAKE_STRING(state);
532
533 send_ucred =
534 (pid != 0 && pid != getpid_cached()) ||
535 getuid() != geteuid() ||
536 getgid() != getegid();
537
538 if (n_fds > 0 || send_ucred) {
539 /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
540 msghdr.msg_controllen =
541 (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
542 (send_ucred ? CMSG_SPACE(sizeof(struct ucred)) : 0);
543
544 msghdr.msg_control = alloca0(msghdr.msg_controllen);
545
546 cmsg = CMSG_FIRSTHDR(&msghdr);
547 if (n_fds > 0) {
548 cmsg->cmsg_level = SOL_SOCKET;
549 cmsg->cmsg_type = SCM_RIGHTS;
550 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
551
552 memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
553
554 if (send_ucred)
555 assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg));
556 }
557
558 if (send_ucred) {
559 struct ucred *ucred;
560
561 cmsg->cmsg_level = SOL_SOCKET;
562 cmsg->cmsg_type = SCM_CREDENTIALS;
563 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
564
565 ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
566 ucred->pid = pid != 0 ? pid : getpid_cached();
567 ucred->uid = getuid();
568 ucred->gid = getgid();
569 }
570 }
571
572 do {
573 /* First try with fake ucred data, as requested */
574 n = sendmsg(fd, &msghdr, MSG_NOSIGNAL);
575 if (n < 0) {
576 if (!send_ucred)
577 return log_debug_errno(errno, "Failed to send notify message to '%s': %m", e);
578
579 /* If that failed, try with our own ucred instead */
580 msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
581 if (msghdr.msg_controllen == 0)
582 msghdr.msg_control = NULL;
583
584 n = 0;
585 send_ucred = false;
586 } else {
587 /* Unless we're using SOCK_STREAM, we expect to write all the contents immediately. */
588 if (type != SOCK_STREAM && (size_t) n < iovec_total_size(msghdr.msg_iov, msghdr.msg_iovlen))
589 return -EIO;
590
591 /* Make sure we only send fds and ucred once, even if we're using SOCK_STREAM. */
592 msghdr.msg_control = NULL;
593 msghdr.msg_controllen = 0;
594 }
595 } while (!iovec_increment(msghdr.msg_iov, msghdr.msg_iovlen, n));
596
597 return 1;
598 }
599
600 _public_ int sd_pid_notify_with_fds(
601 pid_t pid,
602 int unset_environment,
603 const char *state,
604 const int *fds,
605 unsigned n_fds) {
606
607 int r;
608
609 r = pid_notify_with_fds_internal(pid, state, fds, n_fds);
610
611 if (unset_environment)
612 assert_se(unsetenv("NOTIFY_SOCKET") == 0);
613
614 return r;
615 }
616
617 _public_ int sd_pid_notify_barrier(pid_t pid, int unset_environment, uint64_t timeout) {
618 _cleanup_close_pair_ int pipe_fd[2] = EBADF_PAIR;
619 int r;
620
621 if (pipe2(pipe_fd, O_CLOEXEC) < 0)
622 return -errno;
623
624 r = sd_pid_notify_with_fds(pid, unset_environment, "BARRIER=1", &pipe_fd[1], 1);
625 if (r <= 0)
626 return r;
627
628 pipe_fd[1] = safe_close(pipe_fd[1]);
629
630 r = fd_wait_for_event(pipe_fd[0], 0 /* POLLHUP is implicit */, timeout);
631 if (r < 0)
632 return r;
633 if (r == 0)
634 return -ETIMEDOUT;
635
636 return 1;
637 }
638
639 _public_ int sd_notify_barrier(int unset_environment, uint64_t timeout) {
640 return sd_pid_notify_barrier(0, unset_environment, timeout);
641 }
642
643 _public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) {
644 return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0);
645 }
646
647 _public_ int sd_notify(int unset_environment, const char *state) {
648 return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0);
649 }
650
651 _public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) {
652 _cleanup_free_ char *p = NULL;
653 int r;
654
655 if (format) {
656 va_list ap;
657
658 va_start(ap, format);
659 r = vasprintf(&p, format, ap);
660 va_end(ap);
661
662 if (r < 0 || !p)
663 return -ENOMEM;
664 }
665
666 return sd_pid_notify(pid, unset_environment, p);
667 }
668
669 _public_ int sd_notifyf(int unset_environment, const char *format, ...) {
670 _cleanup_free_ char *p = NULL;
671 int r;
672
673 if (format) {
674 va_list ap;
675
676 va_start(ap, format);
677 r = vasprintf(&p, format, ap);
678 va_end(ap);
679
680 if (r < 0 || !p)
681 return -ENOMEM;
682 }
683
684 return sd_pid_notify(0, unset_environment, p);
685 }
686
687 _public_ int sd_pid_notifyf_with_fds(
688 pid_t pid,
689 int unset_environment,
690 const int *fds, size_t n_fds,
691 const char *format, ...) {
692
693 _cleanup_free_ char *p = NULL;
694 int r;
695
696 /* Paranoia check: we traditionally used 'unsigned' as array size, but we nowadays more correctly use
697 * 'size_t'. sd_pid_notifyf_with_fds() and sd_pid_notify_with_fds() are from different eras, hence
698 * differ in this. Let's catch resulting incompatibilites early, even though they are pretty much
699 * theoretic only */
700 if (n_fds > UINT_MAX)
701 return -E2BIG;
702
703 if (format) {
704 va_list ap;
705
706 va_start(ap, format);
707 r = vasprintf(&p, format, ap);
708 va_end(ap);
709
710 if (r < 0 || !p)
711 return -ENOMEM;
712 }
713
714 return sd_pid_notify_with_fds(pid, unset_environment, p, fds, n_fds);
715 }
716
717 _public_ int sd_booted(void) {
718 /* We test whether the runtime unit file directory has been
719 * created. This takes place in mount-setup.c, so is
720 * guaranteed to happen very early during boot. */
721
722 if (laccess("/run/systemd/system/", F_OK) >= 0)
723 return true;
724
725 if (errno == ENOENT)
726 return false;
727
728 return -errno;
729 }
730
731 _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) {
732 const char *s, *p = ""; /* p is set to dummy value to do unsetting */
733 uint64_t u;
734 int r = 0;
735
736 s = getenv("WATCHDOG_USEC");
737 if (!s)
738 goto finish;
739
740 r = safe_atou64(s, &u);
741 if (r < 0)
742 goto finish;
743 if (!timestamp_is_set(u)) {
744 r = -EINVAL;
745 goto finish;
746 }
747
748 p = getenv("WATCHDOG_PID");
749 if (p) {
750 pid_t pid;
751
752 r = parse_pid(p, &pid);
753 if (r < 0)
754 goto finish;
755
756 /* Is this for us? */
757 if (getpid_cached() != pid) {
758 r = 0;
759 goto finish;
760 }
761 }
762
763 if (usec)
764 *usec = u;
765
766 r = 1;
767
768 finish:
769 if (unset_environment && s)
770 assert_se(unsetenv("WATCHDOG_USEC") == 0);
771 if (unset_environment && p)
772 assert_se(unsetenv("WATCHDOG_PID") == 0);
773
774 return r;
775 }