hurdkill.c 3.0 KB

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