aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2015-05-12 21:20:19 +0200
committerLudovic Courtès <ludo@gnu.org>2015-05-12 21:22:52 +0200
commit9e2292ef3d9e2626381f9726c72d71057160b7c3 (patch)
treefc88c4752788939402377a6076a50ddcf5b6e092
parent083b54b7c74a68958fe84b8f627123a030775d1e (diff)
downloadpatches-9e2292ef3d9e2626381f9726c72d71057160b7c3.tar
patches-9e2292ef3d9e2626381f9726c72d71057160b7c3.tar.gz
publish: Add '--listen'.
* guix/scripts/publish.scm (show-help, %options): Add --listen. (getaddrinfo*): New procedure. (%default-options): Add 'address'. (open-server-socket): Replace 'addr' and 'port' with 'address', a sockaddr. (guix-publish): Adjust accordingly. Augment "publishing" message with the actual address. * doc/guix.texi (Invoking guix publish): Document it.
-rw-r--r--doc/guix.texi4
-rw-r--r--guix/scripts/publish.scm58
2 files changed, 47 insertions, 15 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 8654e08b4f..50d51c6c61 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3687,6 +3687,10 @@ The following options are available:
@itemx -p @var{port}
Listen for HTTP requests on @var{port}.
+@item --listen=@var{host}
+Listen on the network interface for @var{host}. The default is to
+accept connections from any interface.
+
@item --user=@var{user}
@itemx -u @var{user}
Change privileges to @var{user} as soon as possible---i.e., once the
diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm
index 86d3a754f3..7bad2619b9 100644
--- a/guix/scripts/publish.scm
+++ b/guix/scripts/publish.scm
@@ -51,6 +51,8 @@ Publish ~a over HTTP.\n") %store-directory)
(display (_ "
-p, --port=PORT listen on PORT"))
(display (_ "
+ --listen=HOST listen on the network interface for HOST"))
+ (display (_ "
-u, --user=USER change privileges to USER as soon as possible"))
(display (_ "
-r, --repl[=PORT] spawn REPL server on PORT"))
@@ -62,6 +64,15 @@ Publish ~a over HTTP.\n") %store-directory)
(newline)
(show-bug-report-information))
+(define (getaddrinfo* host)
+ "Like 'getaddrinfo', but properly report errors."
+ (catch 'getaddrinfo-error
+ (lambda ()
+ (getaddrinfo host))
+ (lambda (key error)
+ (leave (_ "lookup of host '~a' failed: ~a~%")
+ host (gai-strerror error)))))
+
(define %options
(list (option '(#\h "help") #f #f
(lambda _
@@ -76,6 +87,15 @@ Publish ~a over HTTP.\n") %store-directory)
(option '(#\p "port") #t #f
(lambda (opt name arg result)
(alist-cons 'port (string->number* arg) result)))
+ (option '("listen") #t #f
+ (lambda (opt name arg result)
+ (match (getaddrinfo* arg)
+ ((info _ ...)
+ (alist-cons 'address (addrinfo:addr info)
+ result))
+ (()
+ (leave (_ "lookup of host '~a' returned nothing")
+ name)))))
(option '(#\r "repl") #f #t
(lambda (opt name arg result)
;; If port unspecified, use default Guile REPL port.
@@ -83,7 +103,8 @@ Publish ~a over HTTP.\n") %store-directory)
(alist-cons 'repl (or port 37146) result))))))
(define %default-options
- '((port . 8080)
+ `((port . 8080)
+ (address . ,(make-socket-address AF_INET INADDR_ANY 0))
(repl . #f)))
(define (lazy-read-file-sexp file)
@@ -230,11 +251,11 @@ example: \"/foo/bar\" yields '(\"foo\" \"bar\")."
'http
`(#:socket ,socket)))
-(define (open-server-socket addr port)
- "Return a TCP socket bound to ADDR and PORT."
- (let ((sock (socket PF_INET SOCK_STREAM 0)))
+(define (open-server-socket address)
+ "Return a TCP socket bound to ADDRESS, a socket address."
+ (let ((sock (socket (sockaddr:fam address) SOCK_STREAM 0)))
(setsockopt sock SOL_SOCKET SO_REUSEADDR 1)
- (bind sock AF_INET addr port)
+ (bind sock address)
sock))
(define (gather-user-privileges user)
@@ -256,15 +277,19 @@ example: \"/foo/bar\" yields '(\"foo\" \"bar\")."
(define (guix-publish . args)
(with-error-handling
- (let* ((opts (args-fold* args %options
- (lambda (opt name arg result)
- (leave (_ "~A: unrecognized option~%") name))
- (lambda (arg result)
- (leave (_ "~A: extraneuous argument~%") arg))
- %default-options))
- (port (assoc-ref opts 'port))
- (user (assoc-ref opts 'user))
- (socket (open-server-socket INADDR_ANY port))
+ (let* ((opts (args-fold* args %options
+ (lambda (opt name arg result)
+ (leave (_ "~A: unrecognized option~%") name))
+ (lambda (arg result)
+ (leave (_ "~A: extraneuous argument~%") arg))
+ %default-options))
+ (user (assoc-ref opts 'user))
+ (port (assoc-ref opts 'port))
+ (address (let ((addr (assoc-ref opts 'address)))
+ (make-socket-address (sockaddr:fam addr)
+ (sockaddr:addr addr)
+ port)))
+ (socket (open-server-socket address))
(repl-port (assoc-ref opts 'repl)))
;; Read the key right away so that (1) we fail early on if we can't
;; access them, and (2) we can then drop privileges.
@@ -279,7 +304,10 @@ example: \"/foo/bar\" yields '(\"foo\" \"bar\")."
(when (zero? (getuid))
(warning (_ "server running as root; \
consider using the '--user' option!~%")))
- (format #t (_ "publishing ~a on port ~d~%") %store-directory port)
+ (format #t (_ "publishing ~a on ~a, port ~d~%")
+ %store-directory
+ (inet-ntop (sockaddr:fam address) (sockaddr:addr address))
+ (sockaddr:port address))
(when repl-port
(repl:spawn-server (repl:make-tcp-server-socket #:port repl-port)))
(with-store store