about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-12-07T00·16+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-12-07T00·16+0000
commit6a8e60913ac470c704510a733d40d3fab3ecb00d (patch)
tree5e089d76841c314608dbcb85c5f6a6f8ae86a1ea /src/libutil
parent79875c5e42eca2e2d05f439da4b0da778385678a (diff)
* Move killUser() to libutil so that the setuid helper can use it.
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.cc47
-rw-r--r--src/libutil/util.hh5
2 files changed, 52 insertions, 0 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index ae5fe821e78b..5907adc80718 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -707,6 +707,53 @@ void Pid::setSeparatePG(bool separatePG)
 }
 
 
+void killUser(uid_t uid)
+{
+    debug(format("killing all processes running under uid `%1%'") % uid);
+
+    assert(uid != 0); /* just to be safe... */
+
+    /* The system call kill(-1, sig) sends the signal `sig' to all
+       users to which the current process can send signals.  So we
+       fork a process, switch to uid, and send a mass kill. */
+
+    Pid pid;
+    pid = fork();
+    switch (pid) {
+
+    case -1:
+        throw SysError("unable to fork");
+
+    case 0:
+        try { /* child */
+
+            if (setuid(uid) == -1) abort();
+
+	    while (true) {
+		if (kill(-1, SIGKILL) == 0) break;
+		if (errno == ESRCH) break; /* no more processes */
+		if (errno != EINTR)
+		    throw SysError(format("cannot kill processes for uid `%1%'") % uid);
+	    }
+        
+        } catch (std::exception & e) {
+            std::cerr << format("killing processes beloging to uid `%1%': %1%\n")
+                % uid % e.what();
+            quickExit(1);
+        }
+        quickExit(0);
+    }
+    
+    /* parent */
+    if (pid.wait(true) != 0)
+        throw Error(format("cannot kill processes for uid `%1%'") % uid);
+
+    /* !!! We should really do some check to make sure that there are
+       no processes left running under `uid', but there is no portable
+       way to do so (I think).  The most reliable way may be `ps -eo
+       uid | grep -q $uid'. */
+}
+
 
 //////////////////////////////////////////////////////////////////////
 
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index b88508dec30d..b850ee798c7c 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -224,6 +224,11 @@ public:
 };
 
 
+/* Kill all processes running under the specified uid by sending them
+   a SIGKILL. */
+void killUser(uid_t uid);
+
+
 /* Run a program and return its stdout in a string (i.e., like the
    shell backtick operator). */
 string runProgram(Path program);