1 | /* Copyright (C) 1991-2022 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #include <errno.h> |
19 | #include <sys/types.h> |
20 | #include <signal.h> |
21 | #include <hurd.h> |
22 | #include <hurd/port.h> |
23 | #include <hurd/signal.h> |
24 | #include <hurd/msg.h> |
25 | |
26 | /* Send a `sig_post' RPC to process number PID. If PID is zero, |
27 | send the message to all processes in the current process's process group. |
28 | If PID is < -1, send SIG to all processes in process group - PID. |
29 | SIG and REFPORT are passed along in the request message. */ |
30 | error_t |
31 | _hurd_sig_post (pid_t pid, int sig, mach_port_t arg_refport) |
32 | { |
33 | int delivered = 0; /* Set when we deliver any signal. */ |
34 | error_t err; |
35 | mach_port_t proc; |
36 | struct hurd_userlink ulink; |
37 | |
38 | inline void kill_pid (pid_t pid) /* Kill one PID. */ |
39 | { |
40 | err = HURD_MSGPORT_RPC (__proc_getmsgport (proc, pid, &msgport), |
41 | (refport = arg_refport, 0), 0, |
42 | /* If no message port we cannot send signals. */ |
43 | msgport == MACH_PORT_NULL ? EPERM |
44 | : __msg_sig_post (msgport, sig, 0, refport)); |
45 | if (! err) |
46 | delivered = 1; |
47 | } |
48 | |
49 | proc = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink); |
50 | |
51 | if (pid <= 0) |
52 | { |
53 | /* Send SIG to each process in pgrp (- PID). */ |
54 | mach_msg_type_number_t npids = 10, i; |
55 | pid_t pidsbuf[10], *pids = pidsbuf; |
56 | |
57 | err = __proc_getpgrppids (proc, - pid, &pids, &npids); |
58 | if (!err) |
59 | { |
60 | int self = 0; |
61 | for (i = 0; i < npids; ++i) |
62 | if (pids[i] == _hurd_pid) |
63 | /* We must do ourselves last so we are not suspended |
64 | and fail to suspend the other processes in the pgrp. */ |
65 | self = 1; |
66 | else |
67 | { |
68 | kill_pid (pids[i]); |
69 | if (err == ESRCH) |
70 | /* The process died already. Ignore it. */ |
71 | err = 0; |
72 | } |
73 | if (pids != pidsbuf) |
74 | __vm_deallocate (__mach_task_self (), |
75 | (vm_address_t) pids, npids * sizeof (pids[0])); |
76 | |
77 | if (self) |
78 | kill_pid (_hurd_pid); |
79 | } |
80 | } |
81 | else |
82 | kill_pid (pid); |
83 | |
84 | _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, proc); |
85 | |
86 | /* If we delivered no signals, but ERR is clear, this must mean that |
87 | every kill_pid call failed with ESRCH, meaning all the processes in |
88 | the pgrp died between proc_getpgrppids and kill_pid; in that case we |
89 | fail with ESRCH. */ |
90 | return delivered ? 0 : err ?: ESRCH; |
91 | } |
92 | weak_alias (_hurd_sig_post, hurd_sig_post) |
93 | |