#| access to the linux /proc file system Unix processes are identified by integers called process ids (pids). A lot of information about process p can be retrieved by looking in /proc/p (e.g., /proc/1234 for process 1234). The relations here may depend on your flavor of unix, and perhaps even on which version you run. |# (defrelation process :derivation individual-derived :documentation "current process id's as integers" :arity 1 :types (integer) :equivs (=) :nonatomic t :type-enforcements (:none) :tester (lambda (&rest ignore) (declare (ignore ignore)) '(lambda (rel p) (and (integerp p) (> p 0) (directory (format nil "/proc/~a/" p))))) :testeffort 1000 ;; just a wild guess for now :generator (simplegenerator (output) (loop for d in (directory "/proc/*/") as p = (ignore-errors (parse-integer (car (last (pathname-directory d))))) when p collect p) 1e5) :size ((output) 100)) (defrelation process-stat :derivation individual-derived :documentation "relates integer process id to readline of /proc//stat" :arity 2 :types (integer string) :equivs (= equal) :nonatomic t :type-enforcements (:none) :tester (lambda (&rest ignore) (declare (ignore ignore)) '(lambda (rel p stat) (and (integerp p) (> p 0) (ignore-errors (string= stat (with-open-file (f (format nil "/proc/~a/stat" p)) (read-line f))))))) :testeffort 1000 ;; just a wild guess for now :generator ((simplegenerator (p output) (and (integerp p) (> p 0) (ignore-errors (with-open-file (f (format nil "/proc/~a/stat" p)) (read-line f)))) 1e3) (simplemultiplegenerator (output output) (loop for f in (directory "/proc/*/stat" :if-does-not-exist :ignore) ;; if does not exist needed to prevent error from /proc/net/stat/ as p = (ignore-errors (parse-integer (car (last (pathname-directory f))))) as stat = (ignore-errors (with-open-file (file f) (read-line file))) when (integerp p) when (> p 0) collect (list p stat)) 1e5)) :size ((output output) 100 (input output) 1 (output input) 1)) (defrelation read-string-elt :computation individual-derived :documentation "relates string to integer n to nth result of read on string" :arity 3 :equivs (equal equal equal) :tester (lambda (&rest ignore) (declare (ignore ignore)) '(lambda (rel string n result) (and (integerp n) (> n 0) ;; look what I can get away with here ... (ap5::loop for x s.t. (read-string-elt string n x) thereis (equal x result))))) :generator (simplemultiplegenerator (string output output) (with-input-from-string (s string) (loop with eof = (cons nil nil) with r with err for i from 0 do (multiple-value-setq (r err) (ignore-errors (read s nil eof))) until (eq r eof) unless err collect (list i r)))) :size ((input input output) 1 (output output output) nil)) (defrelation read-string-elt= :computation individual-derived :documentation "relates string to integer n to nth result of read on string" :arity 3 :equivs (equal = =) :types (entity integer integer) :tester (lambda (&rest ignore) (declare (ignore ignore)) '(lambda (rel string n result) (and (integerp n) (> n 0) ;; look what I can get away with here ... (ap5::loop for x s.t. (read-string-elt= string n x) thereis (= x result))))) :generator (simplemultiplegenerator (string output output) (with-input-from-string (s string) (loop with eof = (cons nil nil) with r with err for i from 0 do (multiple-value-setq (r err) (ignore-errors (read s nil eof))) until (eq r eof) unless err when (integerp r) collect (list i r)))) :size ((input input output) 1 (output output output) nil)) ;; (listof (x y) s.t. (read-string-elt "asd 1 ))) 3" x y)) ;; => ((0 ASD) (1 1) (5 3)) (defrelation process-parent :definition ((proc parent) s.t. (E (stat) (and (process-stat proc stat) (read-string-elt= stat 3 parent)))) :size ((output output) 100 (input output) 1)) (defrelation process-utime :definition ((proc parent) s.t. (E (stat) (and (process-stat proc stat) (read-string-elt= stat 13 parent)))) :size ((output output) 100 (input output) 1)) (defrelation process-stime :definition ((proc parent) s.t. (E (stat) (and (process-stat proc stat) (read-string-elt= stat 14 parent)))) :size ((output output) 100 (input output) 1)) (defrelation process-starttime :definition ((proc parent) s.t. (E (stat) (and (process-stat proc stat) (read-string-elt= stat 21 parent)))) :size ((output output) 100 (input output) 1)) (defrelation process-vsize :definition ((proc parent) s.t. (E (stat) (and (process-stat proc stat) (read-string-elt= stat 22 parent)))) :size ((output output) 100 (input output) 1)) (defrelation process-rss :definition ((proc parent) s.t. (E (stat) (and (process-stat proc stat) (read-string-elt= stat 23 parent)))) :size ((output output) 100 (input output) 1)) (defrelation process-cmdline :derivation individual-derived :documentation "relates integer process id to readline of /proc//cmdline" :arity 2 :types (integer string) :equivs (= equal) :nonatomic t :type-enforcements (:none) :tester (lambda (&rest ignore) (declare (ignore ignore)) '(lambda (rel p stat) (and (integerp p) (> p 0) (ignore-errors (string= stat (with-open-file (f (format nil "/proc/~a/cmdline" p)) (read-line f))))))) :testeffort 1000 ;; just a wild guess for now :generator ((simplegenerator (p output) (and (integerp p) (> p 0) (ignore-errors (with-open-file (f (format nil "/proc/~a/cmdline" p)) (read-line f)))) 1e3) (simplemultiplegenerator (output output) (loop for f in (directory "/proc/*/cmdline" :if-does-not-exist :ignore) ;; if does not exist needed to prevent error from /proc/net/stat/ as p = (ignore-errors (parse-integer (car (last (pathname-directory f))))) as stat = (ignore-errors (with-open-file (file f) (read-line file))) when (integerp p) when (> p 0) when stat collect (list p stat)) 1e5)) :size ((output output) 100 (input output) 1))