sunet/web-server/start-surflet-server

210 lines
6.6 KiB
Plaintext
Executable File

#!/bin/sh
echo "Loading..."
exec scsh -lel SSAX-4.9/load.scm -lel module-system/load.scm -lel sunet-2.1/load.scm -dm -o surflet-server -e main -s "$0" "$@"
!#
(define-structure surflet-server
(export main ; sh jump entry point
server) ; scsh entry point
(open httpd-core
httpd-make-options
httpd-basic-handlers
httpd-file-directory-handlers
httpd-cgi-handlers
httpd-seval-handlers
surflet-handler
surflet-handler/options
let-opt
scsh
scheme
srfi-37
signals)
(begin
(define (usage)
(format #f
"Usage: start-surflet-server
[-h DIR | --htdocs-dir=DIR] [-s DIR | --surflet-dir=DIR]
[--cgi-bin-dir=DIR]
[-i DIR | --images-dir=DIR] [-p NUM | --port=NUM]
[-l FILE | --log-file-name=FILE] [-r NUM | --requests=NUM]
[--help]
with
htdocs-dir directory of html files (default: root/htdocs)
surflet-dir directory of SUrflet files (default: root/surflets)
cgi-bin-dir directory of cgi files (default: root/cgi-bin)
images-dir directory of images files (default: root/img)
port port server is listening to (default: 8080)
log-file-name directory where to store the logfile in CLF
(default: /tmp/httpd.log)
requests maximal amount of simultaneous requests (default 5)
--help show this help
"))
(define (display-usage)
(display (usage) (current-error-port))
(exit 1))
(define (raise-usage-error msg . info)
(display msg (current-error-port))
(display " --- " (current-error-port))
(for-each
(lambda (i)
(display i (current-error-port))
(display " " (current-error-port)))
info)
(display "\n" (current-error-port))
(exit 1))
(define (parse-arguments arg-list)
(let ((number-option-proc
(lambda (alist-key)
(lambda (option name arg ops)
(cond
((not arg)
(raise-usage-error "Option requires a number" name arg))
((string->number arg)
=> (lambda (n) (cons (cons alist-key n) ops)))
(else
(raise-usage-error "Not a number" arg))))))
(absolute-file-option-proc
(lambda (alist-key)
(lambda (option name arg ops)
(cons (cons alist-key
(absolute-file-name arg)) ops)))))
(let ((htdocs-dir-option
(option '(#\h "htdocs-dir") #t #f
(absolute-file-option-proc 'htdocs-dir)))
(surflet-dir-option
(option '(#\s "surflet-dir") #t #f
(absolute-file-option-proc 'surflet-dir)))
(cgi-bin-dir-option
(option '(#\c "cgi-bin-dir") #t #f
(absolute-file-option-proc 'cgi-bin-dir)))
(images-dir-option
(option '(#\i "images-dir") #t #f
(absolute-file-option-proc 'images-dir)))
(port-option
(option '(#\p "port") #t #f
(number-option-proc 'port)))
(log-file-name-option
(option '(#\l "log-file-name") #t #f
(absolute-file-option-proc 'log-file-name)))
(requests-option
(option '(#\r "requests") #t #f
(number-option-proc 'requests)))
(help-option
(option '(#f "help") #f #f
(lambda (option name arg ops)
(display-usage)))))
(args-fold arg-list
(list htdocs-dir-option surflet-dir-option
cgi-bin-dir-option
images-dir-option port-option
log-file-name-option requests-option
help-option)
(lambda (op name arg ops)
(raise-usage-error
"Unknown command line argument: " op))
cons
'()))))
(define (make-options-from-args cmd-line-args default-options)
(let ((given (parse-arguments cmd-line-args)))
(map (lambda (p)
(or (assoc (car p) given) p))
default-options)))
(define (lookup-option alist option)
(cond
((assoc option alist)
=> cdr)
(else
(error "Internal error, option not found" option alist))))
(define (server . args)
(if (pair? args)
(main `(main ,@(car args)))
(main (list (cwd)))))
(define (become-nobody-if-root)
(cond ((zero? (user-uid))
(set-gid (->gid "nobody"))
(set-uid (->uid "nobody")))))
(define (main args)
(with-cwd
(file-name-directory (car args))
(let* ((default-options
`((htdocs-dir . ,(absolute-file-name "root/htdocs"))
(surflet-dir . ,(absolute-file-name "root/surflets"))
(cgi-bin-dir . ,(absolute-file-name "root/cgi-bin"))
(images-dir . ,(absolute-file-name "root/img"))
(port . 8080)
(log-file-name . "/tmp/httpd.log")
(requests . 5)))
(options (make-options-from-args (cdr args) default-options)))
(format #t "Going to run SUrflet server with:
htdocs-dir: ~a
surflet-dir: ~a
cgi-bin-dir: ~a
images-dir: ~a
port: ~a
log-file-name: ~a
a maximum of ~a simultaneous requests, syslogging activated,
and home-dir-handler (public_html) activated.
"
(lookup-option options 'htdocs-dir)
(lookup-option options 'surflet-dir)
(lookup-option options 'cgi-bin-dir)
(lookup-option options 'images-dir)
(lookup-option options 'port)
(lookup-option options 'log-file-name)
(lookup-option options 'requests))
(httpd
(make-httpd-options
with-port (lookup-option options 'port)
with-root-directory (cwd)
with-simultaneous-requests (lookup-option options 'requests)
with-syslog? #t
with-log-file (lookup-option options 'log-file-name)
with-post-bind-thunk become-nobody-if-root
;; The following settings are made to avoid dns lookups.
with-reported-port (lookup-option options 'port)
with-fqdn "localhost"
with-resolve-ips? #f
with-request-handler
(alist-path-dispatcher
(list
(cons "cgi-bin" (cgi-handler (lookup-option options 'cgi-bin-dir)))
(cons "seval" seval-handler)
(cons "source" (rooted-file-or-directory-handler
(lookup-option options 'surflet-dir)
(with-file-name->content-type
(lambda (file-name)
(if (string-ci=?
(file-name-extension file-name) ".scm")
"text/plain"))
(make-file-directory-options))))
(cons "img" (rooted-file-handler
(lookup-option options 'images-dir)))
(cons "surflet" (surflet-handler
(with-surflet-path
(lookup-option options 'surflet-dir)))))
(tilde-home-dir-handler "public_html"
(rooted-file-or-directory-handler
(lookup-option options 'htdocs-dir)))))))))
))
;; EOF
;;; Local Variables:
;;; mode:scheme
;;; End: