From 08e218c9bd9fdfb1e4dcc5f5e245feea17762471 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Sun, 10 Aug 2003 19:25:02 +0000 Subject: [PATCH] 0.8.2.23 A full and final answer[*] to all the people who keep asking for slightly tangential software to be added to contrib: to wit, a contrib module to automate the downloading and installing of packages that are _not_ part of contrib. * (require 'asdf-install) * (asdf-install:install 'xlunit) or $ sbcl-asdf-install xlunit See contrib/asdf-install/README for more details and scary security-related muttering. Also added a :INITIAL-FUNCTION to SB-EXECUTABLE:MAKE-EXECUTABLE so that files don't have to be written such that the application starts as soon as they're loaded [*] Ha! --- contrib/asdf-install/Makefile | 10 ++ contrib/asdf-install/README | 109 ++++++++++++ contrib/asdf-install/asdf-install | Bin 0 -> 5397 bytes contrib/asdf-install/asdf-install.asd | 35 ++++ contrib/asdf-install/defpackage.lisp | 13 ++ contrib/asdf-install/installer.lisp | 266 ++++++++++++++++++++++++++++++ contrib/asdf-install/loader.lisp | 15 ++ contrib/asdf-module.mk | 6 +- contrib/sb-executable/sb-executable.lisp | 8 +- install.sh | 2 +- version.lisp-expr | 2 +- 11 files changed, 458 insertions(+), 8 deletions(-) create mode 100644 contrib/asdf-install/Makefile create mode 100644 contrib/asdf-install/README create mode 100755 contrib/asdf-install/asdf-install create mode 100644 contrib/asdf-install/asdf-install.asd create mode 100644 contrib/asdf-install/defpackage.lisp create mode 100644 contrib/asdf-install/installer.lisp create mode 100644 contrib/asdf-install/loader.lisp diff --git a/contrib/asdf-install/Makefile b/contrib/asdf-install/Makefile new file mode 100644 index 0000000..5ec18e7 --- /dev/null +++ b/contrib/asdf-install/Makefile @@ -0,0 +1,10 @@ +SYSTEM=asdf-install +EXTRA_INSTALL_TARGETS=asdf-install-install + +include ../asdf-module.mk + +asdf-install-install: asdf-install + if test -f $(INSTALL_ROOT)/bin/sbcl-asdf-install ; then \ + mv $(INSTALL_ROOT)/bin/sbcl-asdf-install $(INSTALL_ROOT)/bin/sbcl-asdf-install.old ; \ + fi + cp asdf-install $(INSTALL_ROOT)/bin/sbcl-asdf-install diff --git a/contrib/asdf-install/README b/contrib/asdf-install/README new file mode 100644 index 0000000..d5928d8 --- /dev/null +++ b/contrib/asdf-install/README @@ -0,0 +1,109 @@ +Downloads and installs an ASDF system or anything else that looks +convincingly like one, including updating the ASDF:*CENTRAL-REGISTRY* +symlinks for all the toplevel .asd files it contains. Please read +this file before use: in particular: this is an automatic tool that +downloads and compiles stuff it finds on the 'net. Please look at the +SECURITY section and be sure you understand the implications + + += USAGE + +This can be used either from within an SBCL instance: + +* (require 'asdf-install) +* (asdf-install:install 'xlunit) ; for example + +or standalone from the shell: + +$ sbcl-asdf-install xlunit + +Each argument may be - + + - The name of a cliki page. asdf-install visits that page and finds + the download location from the `:(package)' tag - usually rendered + as "Download ASDF package from ..." + + - A URL, which is downloaded directly + + - A local tar.gz file, which is installed + + += SECURITY CONCERNS: READ THIS CAREFULLY + +When you invoke asdf-install, you are asking SBCL to download, +compile, and install software from some random site on the web. Given +that it's indirected through a page on CLiki, any malicious third party +doesn't even need to hack the distribution server to replace the +package with something else: he can just edit the link. + +For this reason, we encourage package providers to crypto-sign their +packages (see details at the URL in the PACKAGE CREATION section) and +users to check the signatures. asdf-install has three levels of +automatic signature checking: "on", "off" and "unknown sites", which +can be set using the configuration variables described in +CUSTOMIZATION below. The default is "unknown sites", which will +expect a GPG signature on all downloads except those from +presumed-good sites. The current default presumed-good sites are +CCLAN nodes, and two web sites run by SBCL maintainers: again, see +below for customization details + + += CUSTOMIZATION + +If the file $HOME/.asdf-install exists, it is loaded. This can be +used to override the default values of exported special variables. +Presently these are + +*PROXY* + defaults to $http_proxy environment variable +*CCLAN-MIRROR* + preferred/nearest CCLAN node. See the list at + http://ww.telent.net/cclan-choose-mirror +*SBCL-HOME* + Set from $SBCL_HOME environment variable. This should already be + correct for whatever SBCL is running, if it's been installed correctly +*VERIFY-GPG-SIGNATURES* + Verify GPG signatures for the downloaded packages? + NIL - no, T - yes, :UNKNOWN-LOCATIONS - only for URLs which aren't in CCLAN + and don't begin with one of the prefixes in *SAFE-URL-PREFIXES* +*LOCATIONS* + Possible places in the filesystem to install packages into. See default + value for format +*SAFE-URL-PREFIXES* + List of locations for which GPG signature checking /won't/ be done when + *verify-gpg-signatures* is :unknown-locations + + += PACKAGE CREATION + +If you want to create your own packages that can be installed using this +loader, see the "Making your package downloadable..." section at + + + += HACKERS NOTE + +Listen very carefully: I will say this only as often as it appears to +be necessary to say it. asdf-install is not a good example of how to +write a URL parser, HTTP client, or anything else, really. +Well-written extensible and robust URL parsers, HTTP clients, FTP +clients, etc would definitely be nice things to have, but it would be +nicer to have them in CCLAN where anyone can use them - after having +downloaded them with asdf-install - than in SBCL contrib where they're +restricted to SBCL users and can only be updated once a month via SBCL +developers. This is a bootstrap tool, and as such, will tend to +resist changes that make it longer or dependent on more other +packages, unless they also add to its usefulness for bootstrapping. + + += TODO + +a) gpg signature checking would be better if it actually checked against +a list of "trusted to write Lisp" keys, instead of just "trusted to be +who they say they are" + +e) nice to have: resume half-done downloads instead of starting from scratch +every time. but right now we're dealing in fairly small packages, this is not +an immediate concern + + diff --git a/contrib/asdf-install/asdf-install b/contrib/asdf-install/asdf-install new file mode 100755 index 0000000000000000000000000000000000000000..db1ac64a5ff162d00d2b7fdde677e011ae60802b GIT binary patch literal 5397 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 literal 0 HcmV?d00001 diff --git a/contrib/asdf-install/asdf-install.asd b/contrib/asdf-install/asdf-install.asd new file mode 100644 index 0000000..cdcec0a --- /dev/null +++ b/contrib/asdf-install/asdf-install.asd @@ -0,0 +1,35 @@ +;;; -*- Lisp -*- + +(defpackage #:asdf-install-system + (:use #:cl #:asdf)) + +(in-package #:asdf-install-system) +(require 'sb-executable) + +;;; this is appalling misuse of asdf. please don't treat it as any +;;; kind of example. this shouldn't be a compile-op, or if it is, should +;;; define output-files properly instead oif leaving it be the fasl +(defclass exe-file (cl-source-file) ()) +(defmethod perform ((o compile-op) (c exe-file)) + (call-next-method) + (sb-executable:make-executable + (make-pathname :name "asdf-install" + :type nil + :defaults (component-pathname c)) + (output-files o c) + :initial-function "RUN")) + +(defmethod perform ((o load-op) (c exe-file)) nil) + +(defsystem asdf-install + :depends-on (sb-posix sb-bsd-sockets) + :version "0.2" + :components ((:file "defpackage") + (exe-file "loader") + (:file "installer"))) + +(defmethod perform :after ((o load-op) (c (eql (find-system :asdf-install)))) + (provide 'asdf-install)) + +(defmethod perform ((o test-op) (c (eql (find-system :asdf-install)))) + t) diff --git a/contrib/asdf-install/defpackage.lisp b/contrib/asdf-install/defpackage.lisp new file mode 100644 index 0000000..1b9636b --- /dev/null +++ b/contrib/asdf-install/defpackage.lisp @@ -0,0 +1,13 @@ +(cl:in-package :cl-user) +(defpackage :asdf-install + (:use "CL" "SB-EXT" "SB-BSD-SOCKETS") + (:export + ;; customizable variables + #:*proxy* #:*cclan-mirror* #:*sbcl-home* + #:*verify-gpg-signatures* #:*locations* + #:*safe-url-prefixes* + ;; entry point + #:install)) + +(defpackage :asdf-install-customize + (:use "CL" "SB-EXT" "SB-BSD-SOCKETS" "ASDF-INSTALL")) diff --git a/contrib/asdf-install/installer.lisp b/contrib/asdf-install/installer.lisp new file mode 100644 index 0000000..c8a3551 --- /dev/null +++ b/contrib/asdf-install/installer.lisp @@ -0,0 +1,266 @@ +(in-package :asdf-install) + +(defvar *proxy* (posix-getenv "http_proxy")) +(defvar *cclan-mirror* + (or (posix-getenv "CCLAN_MIRROR") + "http://ftp.linux.org.uk/pub/lisp/cclan/")) + +(defun directorify (name) + ;; input name may or may not have a training #\/, but we know we + ;; want a directory + (let ((path (pathname name))) + (if (pathname-name path) + (merge-pathnames + (make-pathname :directory `(:relative ,(pathname-name path)) + :name "") + path) + path))) + +(defvar *sbcl-home* (directorify (posix-getenv "SBCL_HOME"))) +(defvar *dot-sbcl* + (merge-pathnames (make-pathname :directory '(:relative ".sbcl")) + (user-homedir-pathname))) + +(defvar *verify-gpg-signatures* :unknown-locations + "Should we get detached GPG signatures for the packages and verify them? +NIL - no, T - yes, :UNKNOWN-LOCATIONS - for any URL which isn't in CCLAN +and doesn't begin with one of the prefixes in *SAFE-URL-PREFIXES*") +(defvar *safe-url-prefixes* + (list "http://ftp.linux.org.uk/pub/lisp/" + "http://files.b9.com/")) + +(defun verify-gpg-signatures-p (url) + (labels ((prefixp (prefix string) + (let ((m (mismatch prefix string))) + (or (not m) (>= m (length prefix)))))) + (case *verify-gpg-signatures* + (nil nil) + (:unknown-locations + (notany + (lambda (x) (prefixp x url)) + (cons *cclan-mirror* *safe-url-prefixes*))) + (t t)))) + +(defvar *locations* + `((,(merge-pathnames "site/" *sbcl-home*) + ,(merge-pathnames "site-systems/" *sbcl-home*) + "System-wide install") + (,(merge-pathnames "site/" *dot-sbcl*) + ,(merge-pathnames "systems/" *dot-sbcl*) + "Personal installation"))) + +(let* ((*package* (find-package :asdf-install-customize)) + (file (probe-file (merge-pathnames + (make-pathname :name ".asdf-install") + (user-homedir-pathname))))) + (when file (load file))) + +(define-condition download-error (error) + ((url :initarg :url :reader download-url) + (response :initarg :response :reader download-response)) + (:report (lambda (c s) + (format s "Server responded ~A for GET ~A" + (download-response c) (download-url c))))) + +(define-condition signature-error (error) + ((cause :initarg :cause :reader signature-error-cause)) + (:report (lambda (c s) + (format s "Cannot verify package signature: ~A" + (signature-error-cause c))))) + +(defun url-host (url) + (assert (string-equal url "http://" :end1 7)) + (let* ((port-start (position #\: url :start 7)) + (host-end (min (or (position #\/ url :start 7) (length url)) + (or port-start (length url))))) + (subseq url 7 host-end))) + +(defun url-port (url) + (assert (string-equal url "http://" :end1 7)) + (let ((port-start (position #\: url :start 7))) + (if port-start (parse-integer url :start port-start :junk-allowed t) 80))) + +(defun url-connection (url) + (let ((s (make-instance 'inet-socket :type :stream :protocol :tcp)) + (host (url-host url)) + (port (url-port url))) + (socket-connect + s (car (host-ent-addresses (get-host-by-name (url-host (or *proxy* url))))) + (url-port (or *proxy* url))) + (let ((stream (socket-make-stream s :input t :output t :buffering :full))) + ;; we are exceedingly unportable about proper line-endings here. + ;; Anyone wishing to run this under non-SBCL should take especial care + (format stream "GET ~A HTTP/1.0~%Host: ~A~%Cookie: CCLAN-SITE=~A~%~%" + url host *cclan-mirror*) + (force-output stream) + (list + (let* ((l (read-line stream)) + (space (position #\Space l))) + (parse-integer l :start (1+ space) :junk-allowed t)) + (loop for line = (read-line stream nil nil) + until (or (null line) (eql (elt line 0) (code-char 13))) + collect + (let ((colon (position #\: line))) + (cons (intern (string-upcase (subseq line 0 colon)) :keyword) + (string-trim (list #\Space (code-char 13)) + (subseq line (1+ colon)))))) + stream)))) + +(defun download-files-for-package (package-name-or-url file-name) + (let ((url + (if (= (mismatch package-name-or-url "http://") 7) + package-name-or-url + (format nil "http://www.cliki.net/~A?download" + package-name-or-url)))) + (destructuring-bind (response headers stream) + (block got + (loop + (destructuring-bind (response headers stream) (url-connection url) + (unless (member response '(301 302)) + (return-from got (list response headers stream))) + (close stream) + (setf url (cdr (assoc :location headers)))))) + (if (>= response 400) + (error 'download-error :url url :response response)) + (let ((length (parse-integer + (or (cdr (assoc :content-length headers)) "") + :junk-allowed t))) + (format t "Downloading ~A bytes from ~A ..." + (if length length "some unknown number of") url) + (force-output) + (with-open-file (o file-name :direction :output) + (if length + (let ((buf (make-array length + :element-type + (stream-element-type stream) ))) + (read-sequence buf stream) + (write-sequence buf o)) + (sb-executable:copy-stream stream o)))) + (close stream) + (terpri) + ;; seems to have worked. let's try for a detached gpg signature too + (when (verify-gpg-signatures-p url) + (verify-gpg-signature url file-name))))) + +(defun verify-gpg-signature (url file-name) + (destructuring-bind (response headers stream) + (url-connection (concatenate 'string url ".asc")) + (unwind-protect + (if (= response 200) + ;; sadly, we can't pass the stream directly to run-program, + ;; because (at least in sbcl 0.8) that ignores existing buffered + ;; data and only reads new fresh data direct from the file + ;; descriptor + (let ((data (make-string (parse-integer + (cdr (assoc :content-length headers)) + :junk-allowed t)))) + (read-sequence data stream) + (let ((ret + (process-exit-code + (sb-ext:run-program "gpg" + (list "--verify" "-" + (namestring file-name)) + :output t + :search t + :input (make-string-input-stream data) + :wait t)))) + (unless (zerop ret) + (error 'signature-error + :cause (make-condition + 'simple-error + :format-control "GPG returned exit status ~A" + :format-arguments (list ret)))))) + (error 'signature-error + :cause + (make-condition + 'download-error :url (concatenate 'string url ".asc") + :response response))) + (close stream)))) + + + + +(defun where () + (format t "Install where?~%") + (loop for (source system name) in *locations* + for i from 1 + do (format t "~A) ~A: ~% System in ~A~% Files in ~A ~%" + i name system source)) + (format t " --> ") (force-output) + (let ((response (read))) + (when (> response 0) + (elt *locations* (1- response))))) + +(defun install-package (source system packagename) + "Returns a list of asdf system names for installed asdf systems" + (ensure-directories-exist source ) + (ensure-directories-exist system ) + (let* ((tar + (with-output-to-string (o) + (or + (sb-ext:run-program "tar" + (list "-C" (namestring source) + "-xzvf" (namestring packagename)) + :output o + :search t + :wait t) + (error "can't untar")))) + (dummy (princ tar)) + (pos-slash (position #\/ tar)) + (*default-pathname-defaults* + (merge-pathnames + (make-pathname :directory + `(:relative ,(subseq tar 0 pos-slash))) + source))) + (loop for asd in (directory + (make-pathname :name :wild :type "asd")) + do (let ((target (merge-pathnames + (make-pathname :name (pathname-name asd) + :type (pathname-type asd)) + system))) + (when (probe-file target) + (sb-posix:unlink target)) + (sb-posix:symlink asd target)) + collect (pathname-name asd)))) + +(defvar *temporary-files*) +(defun temp-file-name (p) + (let* ((pos-slash (position #\/ p :from-end t)) + (pos-dot (position #\. p :start (or pos-slash 0)))) + (merge-pathnames + (make-pathname + :name (subseq p (if pos-slash (1+ pos-slash) 0) pos-dot) + :type "asdf-install-tmp")))) + + +;; this is the external entry point +(defun install (&rest packages) + (let ((*temporary-files* nil)) + (unwind-protect + (destructuring-bind (source system name) (where) + (labels ((one-iter (packages) + (dolist (asd + (loop for p in (mapcar 'string packages) + unless (probe-file p) + do (let ((tmp (temp-file-name p))) + (pushnew tmp *temporary-files*) + (download-files-for-package p tmp) + (setf p tmp)) + end + do (format t "Installing ~A in ~A,~A~%" + p source system) + append (install-package source system p))) + (handler-case + (asdf:operate 'asdf:load-op asd) + (asdf:missing-dependency (c) + (format t + "Downloading package ~A, required by ~A~%" + (asdf::missing-requires c) + (asdf:component-name + (asdf::missing-required-by c))) + (one-iter (list + (symbol-name + (asdf::missing-requires c))))))))) + (one-iter packages))) + (dolist (l *temporary-files*) + (when (probe-file l) (delete-file l)))))) diff --git a/contrib/asdf-install/loader.lisp b/contrib/asdf-install/loader.lisp new file mode 100644 index 0000000..7d1211f --- /dev/null +++ b/contrib/asdf-install/loader.lisp @@ -0,0 +1,15 @@ + +(in-package :cl-user) +(eval-when (:compile-toplevel :load-toplevel :execute) + (require 'asdf) + (asdf:operate 'asdf:load-op 'asdf-install :verbose nil)) + +(defun run () + (handler-case + (apply #'asdf-install:install (cdr *posix-argv*)) + (error (c) + (princ "Install failed due to error:") (terpri) + (princ c) (terpri) + (quit :unix-status 1)))) + +;(quit) \ No newline at end of file diff --git a/contrib/asdf-module.mk b/contrib/asdf-module.mk index cdfd9d6..15e5268 100644 --- a/contrib/asdf-module.mk +++ b/contrib/asdf-module.mk @@ -1,7 +1,7 @@ CC=gcc -export CC +export CC SBCL -all: +all: $(EXTRA_ALL_TARGETS) $(MAKE) -C ../asdf $(SBCL) --eval '(load "../asdf/asdf")' \ --eval "(setf asdf::*central-registry* '((MERGE-PATHNAMES \"systems/\" (TRUENAME (SB-EXT:POSIX-GETENV \"SBCL_HOME\")))))" \ @@ -14,6 +14,6 @@ test: all $(SBCL) --eval '(load "../asdf/asdf")' -install: +install: $(EXTRA_INSTALL_TARGETS) tar cf - . | ( cd $(INSTALL_DIR) && tar xpvf - ) ( cd $(SBCL_HOME)/systems && ln -fs ../$(SYSTEM)/$(SYSTEM).asd . ) diff --git a/contrib/sb-executable/sb-executable.lisp b/contrib/sb-executable/sb-executable.lisp index c424d43..b4ba7ed 100644 --- a/contrib/sb-executable/sb-executable.lisp +++ b/contrib/sb-executable/sb-executable.lisp @@ -21,18 +21,20 @@ (defvar *exec-header* "#!/bin/sh -- -exec sbcl --noinform ~{~A ~}--eval \"(with-open-file (i \\\"$0\\\" :element-type '(unsigned-byte 8)) (loop while (< ret 2) when (= (read-byte i) 10) count 1 into ret) (load i) (quit))\" --end-toplevel-options ${1+\"$@\"} +exec sbcl --noinform ~{~A ~}--eval \"(with-open-file (i \\\"$0\\\" :element-type '(unsigned-byte 8)) (loop while (< ret 2) when (= (read-byte i) 10) count 1 into ret) (load i) (funcall (quote ~A)) (quit))\" --end-toplevel-options ${1+\"$@\"} ") (defun make-executable (output-file fasls &key (runtime-flags '("--disable-debugger" "--userinit /dev/null" - "--sysinit /dev/null"))) + "--sysinit /dev/null")) + initial-function) "Write an executable called OUTPUT-FILE which can be run from the shell, by 'linking' together code from FASLS. Actually works by concatenating them and prepending a #! header" (with-open-file (out output-file :direction :output :element-type '(unsigned-byte 8)) (write-sequence (map 'vector #'char-code - (format nil *exec-header* runtime-flags)) out) + (format nil *exec-header* runtime-flags + (or initial-function 'values))) out) (dolist (input-file (if (listp fasls) fasls (list fasls))) (with-open-file (in (merge-pathnames input-file (make-pathname :type "fasl")) diff --git a/install.sh b/install.sh index dee7db4..50c66b6 100644 --- a/install.sh +++ b/install.sh @@ -19,7 +19,7 @@ if [ -n "$SBCL_HOME" -a "$INSTALL_ROOT/lib/sbcl" != "$SBCL_HOME" ];then exit 1 fi SBCL_HOME=$INSTALL_ROOT/lib/sbcl -export SBCL_HOME +export SBCL_HOME INSTALL_ROOT ensure_dirs $INSTALL_ROOT $INSTALL_ROOT/bin $INSTALL_ROOT/lib \ $INSTALL_ROOT/man $INSTALL_ROOT/man/man1 \ $SBCL_HOME $SBCL_HOME/systems $SBCL_HOME/site-systems diff --git a/version.lisp-expr b/version.lisp-expr index 30ef385..d49828d 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.8.2.22" +"0.8.2.23" -- 1.7.10.4