source: project/chicken/branches/hygienic/henrietta.scm @ 11717

Last change on this file since 11717 was 11717, checked in by felix winkelmann, 13 years ago

henrietta writes REMOTE_ADDR to log

File size: 5.4 KB
Line 
1;;;; henrietta.scm - Server program (CGI) for serving eggs from a repository over HTTP
2;
3; Copyright (c) 2008, The Chicken Team
4; All rights reserved.
5;
6; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
7; conditions are met:
8;
9;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
10;     disclaimer.
11;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12;     disclaimer in the documentation and/or other materials provided with the distribution.
13;   Neither the name of the author nor the names of its contributors may be used to endorse or promote
14;     products derived from this software without specific prior written permission.
15;
16; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
17; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24; POSSIBILITY OF SUCH DAMAGE.
25
26
27(require-library setup-download regex extras utils ports srfi-1 posix)
28
29
30(module main ()
31
32  (import scheme chicken regex extras utils ports srfi-1 posix)
33  (import setup-utils setup-download)
34
35  (define *default-transport* 'svn)
36  (define *default-location* (current-directory))
37  (define *test* #f)
38
39  (define (headers)
40    (print "Connection: close\r\nContent-type: text/plain\r\n\r\n"))
41
42  (define (fail msg . args)
43    (pp `(error ,msg ,@args))
44    (cleanup)
45    (exit 0))
46
47  (define (cleanup)
48    (and-let* ((tmpdir (temporary-directory)))
49      (fprintf (current-error-port) "removing temporary directory `~a'~%" tmpdir)
50      (remove-directory tmpdir)))
51
52  (define (retrieve name version)
53    (let ((dir (handle-exceptions ex 
54                   (fail ((condition-property-accessor 'exn 'message) ex)
55                         ((condition-property-accessor 'exn 'arguments) ex))
56                 (retrieve-extension 
57                  name *default-transport* *default-location*
58                  version #t))))
59      (unless dir 
60        (fail "no such extension or version" name version))
61      (let walk ((dir dir) (prefix "."))
62        (let ((files (directory dir)))
63          (for-each
64           (lambda (f)
65             (let ((ff (string-append dir "/" f))
66                   (pf (string-append prefix "/" f)))
67               (cond ((directory? ff)
68                      (print "\n#|--------------------|# \"" pf "/\" 0")
69                      (walk ff pf))
70                     (else
71                      (print "\n#|--------------------|# \"" pf "\" " (file-size ff))
72                      (display (read-all ff))))))
73           files)))
74      (print "\n#!eof") ) )
75
76  (define (service)
77    (let ((qs (getenv "QUERY_STRING"))
78          (ra (getenv "REMOTE_ADDR")))
79      (fprintf (current-error-port) "~%========== serving request from ~a ...~%"
80               (or ra "<unknown>"))
81      (unless qs
82        (error "no QUERY_STRING set"))
83      (let ((m (string-match "[^?]+\\?(.+)" qs))
84            (egg #f)
85            (version #f))
86        (let loop ((qs (if m (cadr m) qs)))
87          (let* ((m (string-search-positions "^(\\w+)=([^&]+)" qs))
88                 (ms (and m (apply substring qs (cadr m))))
89                 (rest (and m (substring qs (cadar m)))))
90            (cond ((not m)
91                   (headers)            ; from here on use `fail'
92                   (cond (*test* 
93                          (fail "test"))
94                         (egg
95                          (retrieve egg version)
96                          (cleanup) )
97                         (else (fail "no extension name specified") ) ))
98                  ((string=? ms "version")
99                   (set! version (apply substring qs (caddr m)))
100                   (loop rest))
101                  ((string=? ms "name")
102                   (set! egg (apply substring qs (caddr m)))
103                   (loop rest))
104                  ((string=? ms "test")
105                   (set! *test* #t)
106                   (loop rest))
107                  (else
108                   (warning "unrecognized query option" ms)
109                   (loop rest))))))))
110 
111
112  (define (usage code)
113    (print #<#EOF
114usage: henrietta [OPTION ...]
115
116  -h   -help                    show this message
117  -l   -location LOCATION       install from given location (default: current directory)
118  -t   -transport TRANSPORT     use given transport instead of default (#{*default-transport*})
119EOF
120);|
121    (exit code))
122
123  (define *short-options* '(#\h #\l #\t))
124
125  (define (main args)
126    (let loop ((args args))
127      (if (null? args)
128          (service)
129          (let ((arg (car args)))
130            (cond ((or (string=? arg "-help") 
131                       (string=? arg "-h")
132                       (string=? arg "--help"))
133                   (usage 0))
134                  ((or (string=? arg "-l") (string=? arg "-location"))
135                   (unless (pair? (cdr args)) (usage 1))
136                   (set! *default-location* (cadr args))
137                   (loop (cddr args)))
138                  ((or (string=? arg "-t") (string=? arg "-transport"))
139                   (unless (pair? (cdr args)) (usage 1))
140                   (set! *default-transport* (string->symbol (cadr args)))
141                   (loop (cddr args)))
142                  ((and (positive? (string-length arg))
143                        (char=? #\- (string-ref arg 0)))
144                   (if (> (string-length arg) 2)
145                       (let ((sos (string->list (substring arg 1))))
146                         (if (null? (lset-intersection eq? *short-options* sos))
147                             (loop (append (map (cut string #\- <>) sos) (cdr args)))
148                             (usage 1)))
149                       (usage 1)))
150                  (else (loop (cdr args))))))))
151
152  (main (command-line-arguments))
153 
154)
Note: See TracBrowser for help on using the repository browser.