summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--guix/build/syscalls.scm29
1 files changed, 28 insertions, 1 deletions
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index 90cacc760b..7a1bad7331 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -22,13 +22,15 @@
   #:use-module (srfi srfi-1)
   #:use-module (ice-9 rdelim)
   #:use-module (ice-9 match)
+  #:use-module (ice-9 ftw)
   #:export (errno
             MS_RDONLY
             MS_REMOUNT
             MS_BIND
             MS_MOVE
             mount
-            umount))
+            umount
+            processes))
 
 ;;; Commentary:
 ;;;
@@ -153,4 +155,29 @@ constants from <sys/mount.h>."
         (when update-mtab?
           (remove-from-mtab target))))))
 
+(define (kernel? pid)
+  "Return #t if PID designates a \"kernel thread\" rather than a normal
+user-land process."
+  (let ((stat (call-with-input-file (format #f "/proc/~a/stat" pid)
+                (compose string-tokenize read-string))))
+    ;; See proc.txt in Linux's documentation for the list of fields.
+    (match stat
+      ((pid tcomm state ppid pgrp sid tty_nr tty_pgrp flags min_flt
+            cmin_flt maj_flt cmaj_flt utime stime cutime cstime
+            priority nice num_thread it_real_value start_time
+            vsize rss rsslim
+            (= string->number start_code) (= string->number end_code) _ ...)
+       ;; Got this obscure trick from sysvinit's 'killall5' program.
+       (and (zero? start_code) (zero? end_code))))))
+
+(define (processes)
+  "Return the list of live processes."
+  (sort (filter-map (lambda (file)
+                      (let ((pid (string->number file)))
+                        (and pid
+                             (not (kernel? pid))
+                             pid)))
+                    (scandir "/proc"))
+        <))
+
 ;;; syscalls.scm ends here