;;; -*-Scheme-*- ;;; ;;; The Scheme layer of the UNIX extension. (require 'record) (require 'recordutil) (require 'unix.so) (define-record-type stat (type mode ino dev nlink uid gid size atime mtime ctime)) (define-record-accessors stat-record) (define (unix-stat fn) (let* ((ret (make-stat-record)) (err (unix-stat-vector-fill! fn (record-values ret)))) (if (unix-error? err) err ret))) (if (feature? 'unix:symlinks) (define (unix-lstat fn) (let* ((ret (make-stat-record)) (err (unix-lstat-vector-fill! fn (record-values ret)))) (if (unix-error? err) err ret)))) (define-record-type time (seconds minutes hours day-of-month month year weekday day-of-year dst)) (define-record-accessors time-record) (define-record-modifiers time-record) (define (unix-decode-localtime t) (let ((ret (make-time-record))) (unix-decode-time-vector-fill! t (record-values ret) #f) ret)) (define (unix-decode-utc t) (let ((ret (make-time-record))) (unix-decode-time-vector-fill! t (record-values ret) #t) ret)) (define (unix-time->string t) (cond ((integer? t) (unix-time->string-internal t)) ((time-record? t) (unix-time->string-internal (record-values t))) (else (error 'unix-time->string "argument must be integer or time-record")))) (define-record-type nanotime (nanoseconds minuteswest dst)) (define-record-accessors nanotime-record) (define (unix-internal-make-nanotime v i) (if (vector-ref v i) (vector-set! v i (+ (* (car (vector-ref v i)) 1000000000) (cdr (vector-ref v i)))))) (define (unix-nanotime) (let* ((ret (make-nanotime-record)) (v (record-values ret))) (unix-nanotime-vector-fill! v) (vector-set! v 0 (+ (* (car (vector-ref v 0)) 1000000000) (cdr (vector-ref v 0)))) ret)) (define-record-type system (hostname sysname osname)) (define-record-accessors system-record) (define (unix-system-info) (let ((ret (make-system-record))) (unix-system-info-vector-fill! (record-values ret)) ret)) (define-record-type passwd (name password uid gid gecos homedir shell)) (define-record-accessors passwd-record) (define (unix-get-passwd . arg) (let* ((ret (make-passwd-record)) (err (apply unix-get-passwd-vector-fill! (record-values ret) arg))) (if (unix-error? err) err ret))) (define-record-type group (name password gid members)) (define-record-accessors group-record) (define (unix-get-group . arg) (let* ((ret (make-group-record)) (err (apply unix-get-group-vector-fill! (record-values ret) arg))) (if (unix-error? err) err ret))) (define-record-type resources (user-time system-time)) (define-record-accessors resources-record) (define (unix-process-resources) (let* ((self (make-resources-record)) (children (make-resources-record)) (v1 (record-values self)) (v2 (record-values children)) (ticks/s (unix-process-resources-vector-fill! v1 v2)) (convert (lambda (ticks) (round (/ (* ticks 1000000000) ticks/s))))) (vector-set! v1 0 (convert (vector-ref v1 0))) (vector-set! v1 1 (convert (vector-ref v1 1))) (vector-set! v2 0 (convert (vector-ref v2 0))) (vector-set! v2 1 (convert (vector-ref v2 1))) (cons self children))) (if (feature? 'unix:file-locking) (begin (define-record-type lock (exclusive? whence start length)) (define-record-accessors lock-record) (define-record-modifiers lock-record) (define (unix-set-lock fd lock wait?) (if (not (lock-record? lock)) (error 'unix-set-lock "argument not a lock-record")) (unix-internal-lock-operation fd (record-values lock) wait? #\s 0)) (define (unix-remove-lock fd lock) (if (not (lock-record? lock)) (error 'unix-remove-lock "argument not a lock-record")) (unix-internal-lock-operation fd (record-values lock) #f #\r 0)) (define (unix-query-lock fd lock) (if (not (lock-record? lock)) (error 'unix-remove-lock "argument not a lock-record")) (let* ((ret (make-lock-record)) (pid (unix-internal-lock-operation fd (record-values lock) #f #\q (record-values ret)))) (if pid (cons pid ret) #f))))) (define-record-type wait (pid status code core-dump? resources)) (define-record-accessors wait-record) (define (unix-wait . options) (let* ((ret (make-wait-record)) (resources ((record-constructor resources-record) #f #f)) (v (record-values ret)) (rv (record-values resources)) (err (apply unix-wait-vector-fill! v rv options))) (unix-internal-make-nanotime rv 0) (unix-internal-make-nanotime rv 1) (vector-set! v 4 resources) (if (unix-error? err) err ret))) (if (feature? 'unix:wait-process) (define (unix-wait-process pid . options) (let* ((ret (make-wait-record)) (resources ((record-constructor resources-record) #f #f)) (v (record-values ret)) (rv (record-values resources)) (err (apply unix-wait-process-vector-fill! v rv pid options))) (unix-internal-make-nanotime rv 0) (unix-internal-make-nanotime rv 1) (vector-set! v 4 resources) (if (unix-error? err) err ret)))) (define (unix-perror str) (format #t "~a: ~E" str)) (define-macro (unix-errval expr) `(fluid-let ((unix-call-standard-error-handler? #f)) ,expr)) ;; also need the opposite of unix-errval (i.e. make sure error is handled) (provide 'unix)