Use args-fold (SRFI-37) for parsing command-line arguments

This commit is contained in:
eknauel 2004-05-11 12:04:10 +00:00
parent 7db04b74e2
commit 704ffae307
2 changed files with 228 additions and 207 deletions

View File

@ -15,14 +15,18 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
httpd-info-gateway httpd-info-gateway
let-opt let-opt
scsh scsh
scheme) scheme
srfi-37)
(begin (begin
(define (usage) (define (usage)
(format #f (format #f
"Usage: start-extended-web-server [-h htdocs-dir] [-c cgi-bin-dir] [-p port] "Usage: start-extended-web-server
[-l log-file-name] [-r requests] [--help] [-h DIR | --htdocs-dir=DIR] [-c DIR | --cgi-bin-dir=DIR ]
[-l FILE | --log-file-name=FILE] [-r NUM | --requests=NUM]
[-p NUM | --port=NUM]
[--help]
with with
htdocs-dir directory of html files (default: web-server/root/htdocs) htdocs-dir directory of html files (default: web-server/root/htdocs)
@ -32,91 +36,92 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
(default: web-server/httpd.log) (default: web-server/httpd.log)
requests maximal amount of simultaneous requests (default 5) requests maximal amount of simultaneous requests (default 5)
--help show this help --help show this help
" "))
))
(define htdocs-dir #f) (define (display-usage)
(define cgi-bin-dir #f) (display (usage) (current-error-port))
(define port #f) (exit 1))
(define log-file-name #f)
(define root #f)
(define simultaneous-requests #f)
(define (init) (define default-options
(set! htdocs-dir "root/htdocs") `((htdocs-dir . ,(absolute-file-name "web-server/root/htdocs"))
(set! cgi-bin-dir "root/cgi-bin") (cgi-bin-dir . ,(absolute-file-name "web-server/root/cgi-bin"))
(set! port "8080") (port . 8080)
(set! log-file-name "httpd.log") (log-file-name . ,(absolute-file-name "web-server/httpd.log"))
(set! root "root") (requests . 5)))
(set! simultaneous-requests "5"))
(define get-options (define (raise-usage-error msg . info)
(let* ((unknown-option-error (display msg (current-error-port))
(lambda (option) (for-each
(format (error-output-port) (lambda (i)
"unknown option `~A'~%try `start-web-server --help'~%" (display i (current-error-port))
option) (display " " (current-error-port)))
(exit 1))) info)
(missing-argument-error (display "\n" (current-error-port))
(lambda (option) (exit 1))
(format (error-output-port)
"option `~A' requires an argument~%try `start-web-server --help'~%" (define (parse-arguments arg-list)
option) (let ((number-option-proc
(exit 1)))) (lambda (alist-key)
(lambda (options) (lambda (option name arg ops)
(let loop ((options options))
(if (null? options)
(begin
(set! htdocs-dir (absolute-file-name htdocs-dir))
(set! log-file-name (absolute-file-name log-file-name))
(set! cgi-bin-dir (absolute-file-name cgi-bin-dir))
(set! port (string->number port))
(set! simultaneous-requests (string->number simultaneous-requests)))
(cond (cond
((string=? (car options) "-h") ((not arg)
(if (null? (cdr options)) (raise-usage-error "Option requires a number" name arg))
(missing-argument-error (car options)) ((string->number arg)
(set! htdocs-dir (cadr options))) => (lambda (n) (cons (cons alist-key n) ops)))
(loop (cddr options)))
((string=? (car options) "-c")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! cgi-bin-dir (cadr options)))
(loop (cddr options)))
((string=? (car options) "-p")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! port (cadr options)))
(loop (cddr options)))
((string=? (car options) "-l")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! log-file-name (cadr options)))
(loop (cddr options)))
((string=? (car options) "-r")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! simultaneous-requests (cadr options)))
(loop (cddr options)))
((string=? (car options) "--help")
(display (usage))
(exit 0))
((string=? (car options) "--dump")
(let ((image-name (if (null? (cdr options))
"server"
(cadr options))))
(dump-scsh-program main image-name))
(exit 0))
(else (else
(unknown-option-error (car options))))))))) (raise-usage-error "Not a number" arg))))))
(absolute-file-name-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-name-proc 'htdocs-dir)))
(cgi-bin-dir-option
(option '(#\c "cgi-bin-dir") #t #f
(absolute-file-name-proc 'cgi-bin-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-name-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 cgi-bin-dir-option
port-option log-file-name-option
requests-option help-option)
(lambda (op name arg ops)
(raise-usage-error
"Unknown command line argument: " name))
cons
'()))))
(define (make-options-from-args cmd-line-args)
(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 (main args) (define (main args)
(with-cwd (with-cwd
(file-name-directory (car (command-line))) (file-name-directory (car (command-line)))
(init) (let ((options (make-options-from-args (cdr args))))
(format #t "reading options: ~s~%" (cdr args))
(get-options (cdr args))
(cond ((zero? (user-uid)) (cond ((zero? (user-uid))
(set-gid (->gid "nobody")) (set-gid (->gid "nobody"))
(set-uid (->uid "nobody")))) (set-uid (->uid "nobody"))))
@ -129,18 +134,18 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
a maximum of ~a simultaneous requests, syslogging activated, a maximum of ~a simultaneous requests, syslogging activated,
and home-dir-handler (public_html) activated. and home-dir-handler (public_html) activated.
" "
htdocs-dir (lookup-option options 'htdocs-dir)
cgi-bin-dir (lookup-option options 'cgi-bin-dir)
port (lookup-option options 'port)
log-file-name (lookup-option options 'log-file-name)
simultaneous-requests) (lookup-option options 'requests))
(httpd (make-httpd-options (httpd (make-httpd-options
with-port port with-port (lookup-option options 'port)
with-root-directory (cwd) with-root-directory (cwd)
with-simultaneous-requests simultaneous-requests with-simultaneous-requests (lookup-option options 'requests)
with-syslog? #t with-syslog? #t
with-log-file log-file-name with-log-file (lookup-option options 'log-file-name)
with-request-handler with-request-handler
(alist-path-dispatcher (alist-path-dispatcher
(list (cons "h" (home-dir-handler "public_html")) (list (cons "h" (home-dir-handler "public_html"))
@ -154,9 +159,11 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
"Generated by rman-gateway")) "Generated by rman-gateway"))
(cons "info" (info-handler #f #f #f (cons "info" (info-handler #f #f #f
"Generated by info-gateway")) "Generated by info-gateway"))
(cons "cgi-bin" (cgi-handler cgi-bin-dir))) (cons "cgi-bin" (cgi-handler
(rooted-file-or-directory-handler htdocs-dir)))))) (lookup-option options 'cgi-bin-dir))))
)) (rooted-file-or-directory-handler
(lookup-option options 'htdocs-dir))))))))
))
;; EOF ;; EOF

View File

@ -11,14 +11,18 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
httpd-file-directory-handlers httpd-file-directory-handlers
httpd-cgi-handlers httpd-cgi-handlers
httpd-seval-handlers httpd-seval-handlers
scheme-with-scsh) scheme-with-scsh
srfi-37)
(begin (begin
(define (usage) (define (usage)
(format #f (format #f
"Usage: start-web-server [-h htdocs-dir] [-c cgi-bin-dir] [-p port] "Usage: start-web-server
[-l log-file-name] [--help] [-h DIR | --htdocs-dir=DIR] [-c DIR | --cgi-bin-dir=DIR]
[-l FILE | --log-file-name=FILE] [-r NUM | --requests=NUM]
[-p NUM | --port=NUM]
[--help]
with with
htdocs-dir directory of html files (default: web-server/root/htdocs) htdocs-dir directory of html files (default: web-server/root/htdocs)
@ -27,75 +31,87 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
log-file-name directory where to store the logfile in CLF log-file-name directory where to store the logfile in CLF
(default: web-server/httpd.log) (default: web-server/httpd.log)
--help show this help --help show this help
" "))
))
(define htdocs-dir #f) (define (display-usage)
(define cgi-bin-dir #f) (display (usage) (current-error-port))
(define port #f) (exit 1))
(define log-file-name #f)
(define root #f)
(define (init) (define default-options
(set! htdocs-dir "root/htdocs") `((htdocs-dir . ,(absolute-file-name "web-server/root/htdocs"))
(set! cgi-bin-dir "root/cgi-bin") (cgi-bin-dir . ,(absolute-file-name "web-server/root/cgi-bin"))
(set! port "8080") (port . 8080)
(set! log-file-name "httpd.log") (log-file-name . ,(absolute-file-name "web-server/httpd.log"))
(set! root "root")) (requests . 5)))
(define get-options (define (raise-usage-error msg . info)
(let* ((unknown-option-error (display msg (current-error-port))
(lambda (option) (for-each
(format (error-output-port) (lambda (i)
"unknown option `~A'~%try `start-web-server --help'~%" (display i (current-error-port))
option) (display " " (current-error-port)))
(exit 1))) info)
(missing-argument-error (display "\n" (current-error-port))
(lambda (option) (exit 1))
(format (error-output-port)
"option `~A' requires an argument~%try `start-web-server --help'~%" (define (parse-arguments arg-list)
option) (let ((number-option-proc
(exit 1)))) (lambda (alist-key)
(lambda (options) (lambda (option name arg ops)
(let loop ((options options))
(if (null? options)
(begin
(set! htdocs-dir (absolute-file-name htdocs-dir))
(set! log-file-name (absolute-file-name log-file-name))
(set! cgi-bin-dir (absolute-file-name cgi-bin-dir))
(set! port (string->number port)))
(cond (cond
((string=? (car options) "-h") ((not arg)
(if (null? (cdr options)) (raise-usage-error "Option requires a number" name arg))
(missing-argument-error (car options)) ((string->number arg)
(set! htdocs-dir (cadr options))) => (lambda (n) (cons (cons alist-key n) ops)))
(loop (cddr options)))
((string=? (car options) "-c")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! cgi-bin-dir (cadr options)))
(loop (cddr options)))
((string=? (car options) "-p")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! port (cadr options)))
(loop (cddr options)))
((string=? (car options) "-l")
(if (null? (cdr options))
(missing-argument-error (car options))
(set! log-file-name (cadr options)))
(loop (cddr options)))
((string=? (car options) "--help")
(display (usage))
(exit 0))
((string=? (car options) "--dump")
(let ((image-name (if (null? (cdr options))
"web-server"
(cadr options))))
(dump-scsh-program main image-name))
(exit 0))
(else (else
(unknown-option-error (car options))))))))) (raise-usage-error "Not a number" arg))))))
(absolute-file-name-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-name-proc 'htdocs-dir)))
(cgi-bin-dir-option
(option '(#\c "cgi-bin-dir") #t #f
(absolute-file-name-proc 'cgi-bin-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-name-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 cgi-bin-dir-option
port-option log-file-name-option
requests-option help-option)
(lambda (op name arg ops)
(raise-usage-error
"Unknown command line argument: " name))
cons
'()))))
(define (make-options-from-args cmd-line-args)
(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 (become-nobody-if-root) (define (become-nobody-if-root)
(cond ((zero? (user-uid)) (cond ((zero? (user-uid))
@ -105,9 +121,7 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
(define (main args) (define (main args)
(with-cwd (with-cwd
(file-name-directory (car (command-line))) (file-name-directory (car (command-line)))
(init) (let ((options (make-options-from-args (cdr args))))
(format #t "reading options: ~s~%" (cdr args))
(get-options (cdr args))
(format #t "Going to run Webserver with: (format #t "Going to run Webserver with:
htdocs-dir: ~a htdocs-dir: ~a
@ -116,25 +130,25 @@ exec scsh -lel SSAX-4.9/load.scm -lel sunet-2.1/load.scm -dm -o http-test -e mai
log-file-name: ~a log-file-name: ~a
syslogging activated. syslogging activated.
" "
htdocs-dir (lookup-option options 'htdocs-dir)
cgi-bin-dir (lookup-option options 'cgi-bin-dir)
port (lookup-option options 'port)
log-file-name) (lookup-option options 'log-file-name))
(httpd (make-httpd-options (httpd (make-httpd-options
with-port port with-port (lookup-option options 'port)
with-root-directory (cwd) with-root-directory (cwd)
with-syslog? #t with-syslog? #t
with-log-file log-file-name with-log-file (lookup-option options 'log-file-name)
with-post-bind-thunk become-nobody-if-root with-post-bind-thunk become-nobody-if-root
with-request-handler with-request-handler
(alist-path-dispatcher (alist-path-dispatcher
(list (cons "cgi-bin" (cgi-handler cgi-bin-dir)) (list (cons "cgi-bin" (cgi-handler (lookup-option options 'cgi-bin-dir)))
(cons "seval" seval-handler)) (cons "seval" seval-handler))
(tilde-home-dir-handler "public_html" (tilde-home-dir-handler "public_html"
(rooted-file-or-directory-handler (rooted-file-or-directory-handler
htdocs-dir))))))) (lookup-option options 'htdocs-dir)))))))))
)) ))
;; EOF ;; EOF
;;; Local Variables: ;;; Local Variables: