Fix format to match expected output.
[kopensolaris-gnu/glibc.git] / hurd / hurdkill.c
index 3d2af49..e633690 100644 (file)
@@ -1,20 +1,20 @@
-/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
 
 #include <errno.h>
 #include <sys/types.h>
@@ -22,82 +22,72 @@ Cambridge, MA 02139, USA.  */
 #include <hurd.h>
 #include <hurd/port.h>
 #include <hurd/signal.h>
+#include <hurd/msg.h>
 
 /* Send a `sig_post' RPC to process number PID.  If PID is zero,
    send the message to all processes in the current process's process group.
    If PID is < -1, send SIG to all processes in process group - PID.
    SIG and REFPORT are passed along in the request message.  */
 error_t
-_hurd_sig_post (pid_t pid, int sig, mach_port_t refport)
+_hurd_sig_post (pid_t pid, int sig, mach_port_t arg_refport)
 {
   int delivered = 0;           /* Set when we deliver any signal.  */
   error_t err;
-  mach_port_t oneport, *ports;
-  pid_t *pids;
-  mach_msg_type_number_t npids, nports, i;
   mach_port_t proc;
   struct hurd_userlink ulink;
 
+  inline void kill_pid (pid_t pid) /* Kill one PID.  */
+    {
+      err = HURD_MSGPORT_RPC (__proc_getmsgport (proc, pid, &msgport),
+                             (refport = arg_refport, 0), 0,
+                             /* If no message port we cannot send signals.  */
+                             msgport == MACH_PORT_NULL ? EPERM :
+                             __msg_sig_post (msgport, sig, 0, refport));
+      if (! err)
+       delivered = 1;
+    }
+
   proc = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink);
 
   if (pid <= 0)
     {
       /* Send SIG to each process in pgrp (- PID).  */
-      proccoll_t pcoll;
-      err = __proc_pgrp_pcoll (proc, - pid, &pcoll);
+      mach_msg_type_number_t npids = 10, i;
+      pid_t pidsbuf[10], *pids = pidsbuf;
+
+      err = __proc_getpgrppids (proc, - pid, &pids, &npids);
       if (!err)
        {
-         err = __proc_get_collports (proc, pcoll,
-                                     &pids, &npids,
-                                     &ports, &nports);
-         __mach_port_deallocate (__mach_task_self (), pcoll);
+         int self = 0;
+         for (i = 0; i < npids; ++i)
+           if (pids[i] == _hurd_pid)
+             /* We must do ourselves last so we are not suspended
+                and fail to suspend the other processes in the pgrp.  */
+             self = 1;
+           else
+             {
+               kill_pid (pids[i]);
+               if (err == ESRCH)
+                 /* The process died already.  Ignore it.  */
+                 err = 0;
+             }
+         if (pids != pidsbuf)
+           __vm_deallocate (__mach_task_self (),
+                            (vm_address_t) pids, npids * sizeof (pids[0]));
+
+         if (self)
+           kill_pid (_hurd_pid);
        }
     }
   else
-    {
-      err = __proc_getmsgport (proc, pid, &oneport);
-      npids = 1;
-      pids = &pid;
-      ports = &oneport;
-      nports = 1;
-    }
+    kill_pid (pid);
 
-  if (npids != nports)
-    {
-      /* This is scrod.  We can't reasonably try to deliver any signals.  */
-      err = EGRATUITOUS;
-      goto out;
-    }
-    
-  for (i = 0; i < nports; ++i)
-    {
-      int tried = 0;
-      do
-       {
-         mach_port_t msgport;
-         if (tried)
-           {
-             if (err = __proc_getmsgport (proc, pids[i], &msgport))
-               break;
-           }
-         else
-           {
-             msgport = ports[i];
-             tried = 1;
-           }
-         err = __sig_post (msgport, sig, refport);
-         __mach_port_deallocate (__mach_task_self (), msgport);
-       } while (err != MACH_SEND_INVALID_DEST && err != MIG_SERVER_DIED);
-      if (! err)
-       delivered = 1;
-    }
-
- out:
   _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, proc);
 
-  if (ports != &oneport)
-    __vm_deallocate (__mach_task_self (),
-                    (vm_address_t) ports, nports * sizeof (ports[0]));
-
-  return delivered ? 0 : err;
+  /* If we delivered no signals, but ERR is clear, this must mean that
+     every kill_pid call failed with ESRCH, meaning all the processes in
+     the pgrp died between proc_getpgrppids and kill_pid; in that case we
+     fail with ESRCH.  */
+  return delivered ? 0 : err ?: ESRCH;
 }
+weak_alias (_hurd_sig_post, hurd_sig_post)