summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtyom V. Poptsov <poptsov.artyom@gmail.com>2015-10-28 06:14:39 +0300
committerArtyom V. Poptsov <poptsov.artyom@gmail.com>2015-10-28 06:14:39 +0300
commit59d3fd6d6e2e403d10926ed772b36684c5780871 (patch)
treec92082e0530f0b317086a5a940d0f5c417ba0bcd
parentdoc/api-sftp.texi: Add to the repository (diff)
downloadguile-ssh-59d3fd6d6e2e403d10926ed772b36684c5780871.tar.gz
examples/sscp.scm.in: Add to the repository
* examples/sscp.scm.in: Add to the repository. * examples/Makefile.am: Update.
-rw-r--r--examples/Makefile.am8
-rw-r--r--examples/sscp.scm.in99
2 files changed, 104 insertions, 3 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 0c79edc..8065719 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -23,12 +23,13 @@ EXTRA_DIST = \
echo/client.scm.in \
rrepl.scm.in \
rpc/client.scm.in \
- rpc/server.scm.in
+ rpc/server.scm.in \
+ sscp.scm.in
examplesdir = $(pkgdatadir)/examples
examples_echodir = $(pkgdatadir)/examples/echo
examples_rpcdir = $(pkgdatadir)/examples/rpc
-dist_examples_DATA = README sssh.scm ssshd.scm rrepl.scm
+dist_examples_DATA = README sssh.scm ssshd.scm rrepl.scm sscp.scm
dist_examples_echo_DATA = echo/server.scm echo/client.scm
dist_examples_rpc_DATA = rpc/client.scm rpc/server.scm
@@ -45,4 +46,5 @@ CLEANFILES = \
sssh.scm ssshd.scm \
echo/server.scm echo/client.scm \
rrepl.scm \
- rpc/server.scm rpc/client.scm
+ rpc/server.scm rpc/client.scm \
+ sscp.scm
diff --git a/examples/sscp.scm.in b/examples/sscp.scm.in
new file mode 100644
index 0000000..38a8d58
--- /dev/null
+++ b/examples/sscp.scm.in
@@ -0,0 +1,99 @@
+#!@GUILE@ \
+--debug -e main
+!#
+
+;;; sscp.scm -- Scheme Secure Copy implementation.
+
+;; Copyright (C) 2015 Artyom V. Poptsov <poptsov.artyom@gmail.com>
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+;;; Commentary:
+
+;; Somewhat a minimal implementation of scp (Secure Copy) in Scheme that is
+;; aimed to show how one could use (ssh sftp) module from Guile-SSH to do such
+;; a work.
+
+;;; Code:
+
+(use-modules (ice-9 regex) ; 'make-regexp' etc
+ (ice-9 rdelim) ; 'read-line', 'write-line'
+ (ice-9 getopt-long) ; CLI options parsing
+ ;; Guile-SSH modules
+ (ssh session) ; Guile-SSH sessions
+ (ssh auth) ; Authentication
+ (ssh sftp)) ; SFTP client API
+
+
+
+(define (debug fmt . args)
+ (format #t "DEBUG: ~a~%" (apply format #f fmt args)))
+
+(define (print-help-and-exit)
+ (display "
+Usage: sscp source dest
+
+Example:
+ sscp avp@127.0.0.1:/etc/profile profile
+")
+ (exit 0))
+
+
+(define %remote-regex
+ (make-regexp "(.*)@([0-9]+\\.[0-9]+\\.[0-9]\\.[0-9]+):(.*)"))
+
+(define (cp user host path destination)
+ "Copy a file specified by a PATH from HOST to a local DESTINATION."
+ (let ((session (make-session #:user user #:host host)))
+ (connect! session)
+ (userauth-agent! session)
+ (let ((sftp-session (make-sftp-session session)))
+ (let ((remote-file (sftp-open-file sftp-session path O_RDONLY))
+ (local-file (open-output-file destination)))
+ (let copy ((line (read-line remote-file)))
+ (unless (eof-object? line)
+ (write-line line local-file)
+ (copy (read-line remote-file))))))))
+
+
+(define (main args)
+ "Entry point."
+ (let* ((option-spec '((help (single-char #\h) (value #f))))
+ (options (getopt-long args option-spec))
+ (help-needed? (option-ref options 'help #f))
+ (args (option-ref options '() #f)))
+
+ (and help-needed?
+ (print-help-and-exit))
+
+ (debug "program args: ~a" args)
+
+ (let* ((source (car args))
+ (destination (cadr args)))
+
+ (debug "source: ~a; dest: ~a" source destination)
+
+ (cond
+ ((regexp-exec %remote-regex source) =>
+ (lambda (match)
+ (let ((user (match:substring match 1))
+ (host (match:substring match 2))
+ (path (match:substring match 3)))
+ (debug "user: ~a; host: ~a; path: ~a" user host path)
+ (cp user host path destination))))
+ (else
+ (error "Not supported yet. :-/" args))))))
+
+;;; sscp.scm ends here.