189 lines
7.9 KiB
Scheme
189 lines
7.9 KiB
Scheme
(define-c-library libc
|
|
'("stdlib.h" "string.h" "stdio.h" "glob.h" "unistd.h")
|
|
#f
|
|
())
|
|
(define-c-procedure c-perror libc 'perror 'void '(pointer))
|
|
(define (perror procedure-name msg . objs)
|
|
(let ((procedure-name* (string->c-bytevector
|
|
(string-append procedure-name " error"))))
|
|
(c-perror procedure-name*)
|
|
(c-bytevector-free procedure-name*))
|
|
(apply error (cons (string-append procedure-name " error: ") objs)))
|
|
|
|
|
|
(define *temp-file-template*
|
|
(cond ((get-environment-variable "TMPDIR")
|
|
(string-append (get-environment-variable "TMPDIR")
|
|
"/"
|
|
(number->string (pid))
|
|
".~a"))
|
|
(else
|
|
(string-append "/var/tmp/" (number->string (pid)) ".~a"))))
|
|
|
|
(define (->uid uid/username)
|
|
(cond
|
|
((exact-integer? uid/username) uid/username)
|
|
((string? uid/username)
|
|
(letrec*
|
|
((username-length (string-length uid/username))
|
|
(looper (lambda (line)
|
|
(if (eof-object? line)
|
|
#f
|
|
(let ((line-length (string-length line)))
|
|
(if (and (>= line-length username-length)
|
|
(string=? uid/username
|
|
(string-copy line
|
|
0
|
|
username-length)))
|
|
(string->number (list-ref (string-split line #\:) 2))
|
|
(looper (read-line))))))))
|
|
(with-input-from-file "/etc/passwd" (lambda () (looper (read-line))))))
|
|
(else (error (string-append "->uid error: uid/username must be either"
|
|
" exact integer or string")))))
|
|
|
|
(define (->username uid/username)
|
|
(cond ((string? uid/username) uid/username)
|
|
((exact-integer? uid/username)
|
|
(letrec*
|
|
((looper (lambda (line)
|
|
(if (eof-object? line)
|
|
#f
|
|
(let* ((line-length (string-length line))
|
|
(line-list (string-split line #\:))
|
|
(line-list-length (length line-list)))
|
|
(if (and (>= line-list-length 3)
|
|
(= (string->number (list-ref line-list 2))
|
|
uid/username))
|
|
(car line-list)
|
|
(looper (read-line))))))))
|
|
(with-input-from-file "/etc/passwd" (lambda () (looper (read-line))))))
|
|
(else (error (string-append "->username error: uid/username must be either"
|
|
" exact integer or string")))))
|
|
|
|
(define-c-procedure c-realpath libc 'realpath 'pointer '(pointer pointer))
|
|
(define (absolute-file-name fname . dir)
|
|
(cond ((not (string? fname))
|
|
(error "abosolute-file-name error: fname must bes string"))
|
|
((= (string-length fname) 0) "/")
|
|
(else (let* ((fname* (string->c-bytevector fname))
|
|
(path* (c-realpath fname* (c-bytevector-null))))
|
|
(if (c-bytevector-null? path*)
|
|
(let ((error* (string->c-bytevector "absolute-file-name")))
|
|
(c-perror error*)
|
|
(c-bytevector-free fname* path* error*)
|
|
(error "" fname))
|
|
(let ((path (c-bytevector->string path*)))
|
|
(c-bytevector-free fname* path*)
|
|
path))))))
|
|
|
|
(define-c-procedure c-glob libc 'glob 'int '(pointer int pointer pointer))
|
|
(define-c-procedure c-globfree libc 'globfree 'int '(pointer))
|
|
(define-c-struct-type glob-struct '((gl_pathc int) (gl_pathv pointer) (gl_offs int)))
|
|
(define glob
|
|
(lambda paths
|
|
(let ((result '()))
|
|
(for-each
|
|
(lambda (path)
|
|
(let ((glob-struct* (make-c-bytevector (c-type-size glob-struct)))
|
|
(path* (string->c-bytevector path)))
|
|
(c-glob path* 0 (c-bytevector-null) glob-struct*)
|
|
(letrec
|
|
((path-count (c-bytevector-ref glob-struct* glob-struct 'gl_pathc))
|
|
(looper
|
|
(lambda (count)
|
|
(when (< count path-count)
|
|
(let* ((list-path*
|
|
(c-bytevector-ref
|
|
(c-bytevector-ref glob-struct* glob-struct 'gl_pathv)
|
|
'pointer
|
|
(* (c-type-size 'pointer) count)))
|
|
(list-path-string (c-bytevector->string list-path*)))
|
|
(set! result (append result (list list-path-string)))
|
|
(c-bytevector-free list-path*)
|
|
(looper (+ count 1)))))))
|
|
(looper 0)
|
|
(c-bytevector-free path* glob-struct*))))
|
|
paths)
|
|
result)))
|
|
|
|
(define-c-procedure c-setsid libc 'setsid 'int '())
|
|
(define (become-session-leader)
|
|
(let ((result (c-setsid)))
|
|
(when (< result 0)
|
|
(error "become-session-leader error: Most propably already session leader"
|
|
result))
|
|
result))
|
|
|
|
(define-c-procedure c-chdir libc 'chdir 'int '(pointer))
|
|
(define chdir
|
|
(lambda args
|
|
(let ((fname (if (null? args) (home-dir) (car args))))
|
|
(when (not (string? fname)) (error "chdir error: fname must be string"))
|
|
(let* ((fname* (string->c-bytevector fname))
|
|
(result (c-chdir fname*)))
|
|
(c-bytevector-free fname*)
|
|
(when (= result -1)
|
|
(perror "chdir" "could not change directory"))))))
|
|
|
|
(define-c-procedure c-getcwd libc 'getcwd 'pointer '(pointer int))
|
|
(define (cwd)
|
|
(letrec
|
|
((start-size 128)
|
|
(looper
|
|
(lambda (size)
|
|
(let* ((buffer* (make-c-bytevector size))
|
|
(cwd* (c-getcwd buffer* size)))
|
|
(if (c-bytevector-null? cwd*)
|
|
(looper (* size 2))
|
|
(let ((result (c-bytevector->string buffer*)))
|
|
(c-bytevector-free cwd* buffer*)
|
|
result))))))
|
|
(looper start-size)))
|
|
|
|
(define (delete-filesys-object fname)
|
|
(when (not (string? fname))
|
|
(error "delete-filesys-object error: fname must be string"))
|
|
(if (file-directory? fname #f)
|
|
(delete-directory fname)
|
|
(guard (condition (else #t))
|
|
(delete-file fname))))
|
|
|
|
(define (file-directory? fname/port . chase?)
|
|
(when (not (or (string? fname/port)
|
|
(port? fname/port)))
|
|
(error "file-directory? error: fname/port must be string or port"))
|
|
(when (and (not (null? chase?))
|
|
(not (equal? (car chase?) #t))
|
|
(not (equal? (car chase?) #f)))
|
|
(error "file-directory? error: chase? must be boolean"))
|
|
(let ((f-info (file-info fname/port (if (null? chase?) #t (car chase?)))))
|
|
(file-info-directory? f-info)))
|
|
|
|
(define home-dir
|
|
(lambda args
|
|
(let ((user (if (null? args)
|
|
(user-info:name (user-info (user-uid)))
|
|
(car args))))
|
|
(when (not (string? user))
|
|
(error "home-dir error: user must be string" user))
|
|
(letrec
|
|
((username-length (string-length user))
|
|
(looper (lambda (line)
|
|
(if (eof-object? line)
|
|
#f
|
|
(let ((line-length (string-length line)))
|
|
(if (and (>= line-length username-length)
|
|
(string=? user
|
|
(string-copy line
|
|
0
|
|
username-length)))
|
|
(list-ref (string-split line #\:) 5)
|
|
(looper (read-line)))))))
|
|
(home-dir-path (with-input-from-file
|
|
"/etc/passwd"
|
|
(lambda () (looper (read-line))))))
|
|
(when (not home-dir-path)
|
|
(error "home-dir error: home directory not found, user does not exist?"
|
|
user))
|
|
home-dir-path))))
|