;;; This file is part of the Scheme Untergrund Library. ;;; Copyright (c) 2002-2003 by Martin Gasbichler. ;;; For copyright information, see the file COPYING which comes with ;;; the distribution. (define-record-type process-info :process-info (really-make-process-info pid ppid logname real-uid effective-uid saved-set-uid real-gid effective-gid saved-set-gid time %cpu tty executable command-line) process-info? (pid process-info-pid) (ppid process-info-ppid) (logname process-info-logname) (real-uid process-info-real-uid) (effective-uid process-info-effective-uid) (saved-set-uid process-info-saved-set-uid) (real-gid process-info-real-gid) (effective-gid process-info-effective-gid) (saved-set-gid process-info-saved-set-gid) (time process-info-time) (%cpu process-info-%cpu) (tty process-info-tty) (executable process-info-executable) (command-line process-info-command-line)) (define-record-discloser :process-info (lambda (pi) (list 'pi (process-info-pid pi) (process-info-executable pi) (process-info-logname pi)))) (define (make-process-info-with-restlist ps-functions pid ppid logname real-uid effective-uid saved-set-uid real-gid effective-gid saved-set-gid time %cpu tty executable . command-line) (really-make-process-info (string->number pid) (string->number ppid) logname (string->number real-uid) (string->number effective-uid) (string->number saved-set-uid) (string->number real-gid) (string->number effective-gid) (string->number saved-set-gid) ((ps-time->seconds ps-functions) time) (string->number %cpu) tty executable command-line)) (define *os-pss* '()) (define (add-ps! ps-functions) (set! *os-pss* (cons ps-functions *os-pss*))) (define (pps) (let ((os (uname:os-name (uname)))) (let lp ((os-pss *os-pss*)) (if (null? *os-pss*) (error "ps not defined for " os) (let ((next (car os-pss))) (if (string=? os (ps-uname-string next)) (call-ps next) (lp (cdr os-pss)))))))) (define (call-ps ps-functions) (map (lambda (line) (apply make-process-info-with-restlist ps-functions ((ps-line-splitter ps-functions) line))) ((ps-command ps-functions)))) (define-record-type ps-functions :ps-functions (really-make-ps-functions uname-string command time->seconds line-splitter) ps-functions? (uname-string ps-uname-string) (command ps-command) (time->seconds ps-time->seconds) (line-splitter ps-line-splitter)) (define (make-ps-functions uname-string command time->seconds . maybe-line-splitter) (really-make-ps-functions uname-string command time->seconds (if (null? maybe-line-splitter) (sloppy-suffix-splitter) (car maybe-line-splitter)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; FreeBSD (define (fbsd-ps-command) (let ((res (run/strings (ps -axww ;; uses rgid instead of gid "-opid,ppid,user,ruid,uid,svuid,rgid,rgid,svgid,time,%cpu,tty,ucomm,command")))) (if (null? res) (error "ps failed") (cdr res)))) (define fbsd-time->seconds ; hmm, what does the output look like for older processes?? (let ((short-rx (rx (: (submatch (+ digit)) #\: (submatch (: digit digit)) #\. (submatch (: digit digit)))))) (lambda (time) (let ((match-data (regexp-search short-rx time))) (if match-data (+ (* 60 60 (string->number (match:substring match-data 1))) (* 60 (string->number (match:substring match-data 2))) (quotient (string->number (match:substring match-data 3)) 50)) 0))))) (define fbsd-ps (make-ps-functions "FreeBSD" fbsd-ps-command fbsd-time->seconds)) (add-ps! fbsd-ps) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Darwin (define (darwin-ps-command) (let ((res (run/strings (ps -axww ;; uses rgid instead of gid "-opid,ppid,user,ruid,uid,svuid,rgid,svgid,time,tty,ucomm,command")))) (if (null? res) (error "ps failed") (cdr res)))) (define (darwin-line-splitter line) (let ((line-as-list ((sloppy-suffix-splitter) line))) (append (take line-as-list 7) (list (list-ref line-as-list 7)) (drop line-as-list 7)))) (define darwin-ps (make-ps-functions "Darwin" darwin-ps-command fbsd-time->seconds darwin-line-splitter)) (add-ps! darwin-ps) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Linux (define (linux-ps-command) (let ((res (run/strings (ps -A ;axww "-opid,ppid,user,ruid,uid,svuid,rgid,gid,svgid,time,%cpu,tty,ucomm,command")))) (if (null? res) (error "ps failed") (cdr res)))) (define linux-time->seconds ; hmm, what does the output look like for older processes?? (let ((short-rx (rx (: (submatch (+ digit)) #\: (submatch (: digit digit)) #\: (submatch (: digit digit)))))) (lambda (time) (let ((match-data (regexp-search short-rx time))) (if match-data (+ (* 60 60 (string->number (match:substring match-data 1))) (* 60 (string->number (match:substring match-data 2))) (string->number (match:substring match-data 3))) 0))))) (define linux-ps (make-ps-functions "Linux" linux-ps-command linux-time->seconds)) (add-ps! linux-ps) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AIX (define (aix-ps-command) (let ((res (run/strings (ps -A ;; uses ruid/rgid instead of svuid/svgid -opid -oppid -ouser -oruid -ouid -oruid -orgid -ogid -orgid -otime -opcpu -otty -oucomm -oargs)))) (if (null? res) (error "ps failed") (cdr res)))) (define aix-time->seconds (let ((short-rx (rx (: (? (submatch (** 1 3 digit)) #\-) (submatch (** 1 2 digit)) #\: (submatch (: digit digit)) #\: (submatch (: digit digit)))))) (lambda (time) (let ((match-data (regexp-search short-rx time))) (if match-data (+ (if (match:substring match-data 1) (* 24 60 60 (string->number (match:substring match-data 1))) 0) (* 60 60 (string->number (match:substring match-data 2))) (* 60 (string->number (match:substring match-data 3))) (string->number (match:substring match-data 4))) (error "cannot parse time" time)))))) (define aix-ps (make-ps-functions "AIX" aix-ps-command aix-time->seconds)) (add-ps! aix-ps) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Solaris (define (solaris-ps-command) (let ((res (run/strings (ps -A ;; uses ruid/rgid instead of svuid/svgid -opid -oppid -ouser -oruid -ouid -oruid -orgid -ogid -orgid -otime -opcpu -otty -ocomm -oargs)))) (if (null? res) (error "ps failed") (cdr res)))) (define solaris-time->seconds (let ((short-rx (rx (: (? (submatch (** 1 3 digit)) #\-) (? (submatch (** 1 2 digit)) #\:) (submatch (** 1 2 digit)) #\: (submatch (: digit digit)))))) (lambda (time) (let ((match-data (regexp-search short-rx time))) (if match-data (+ (if (match:substring match-data 1) (* 24 60 60 (string->number (match:substring match-data 1))) 0) (if (match:substring match-data 2) (* 60 60 (string->number (match:substring match-data 2))) 0) (* 60 (string->number (match:substring match-data 3))) (string->number (match:substring match-data 4))) (error "cannot parse time" time)))))) (define solaris-ps (make-ps-functions "SunOS" solaris-ps-command solaris-time->seconds)) (add-ps! solaris-ps)