diff options
| -rw-r--r-- | NEWS | 4 | ||||
| -rw-r--r-- | doc/api-sessions.texi | 28 | ||||
| -rw-r--r-- | libguile-ssh/session-func.c | 39 | ||||
| -rw-r--r-- | modules/ssh/session.scm | 23 | ||||
| -rw-r--r-- | tests/common.scm | 3 | ||||
| -rw-r--r-- | tests/config | 4 | ||||
| -rw-r--r-- | tests/session.scm | 8 |
7 files changed, 108 insertions, 1 deletions
@@ -36,6 +36,10 @@ Copyright (C) Artyom V. Poptsov <poptsov.artyom@gmail.com> ** New procedures *** New procedure 'node-server-running?' in (ssh dist node) *** New procedure 'node-run-server' in (ssh dist node) +*** New procedure 'session-parse-config!' in (ssh session) +** 'make-session' now takes 'config' option + that allows to specify whether the SSH config should be parsed or not, and + optionally the path to the config. ** Unit tests *** Expand the test suite for distributed forms *** Expand the test suite for tunnels diff --git a/doc/api-sessions.texi b/doc/api-sessions.texi index b150f64..7330d92 100644 --- a/doc/api-sessions.texi +++ b/doc/api-sessions.texi @@ -223,10 +223,38 @@ slower. Set callbacks that will be called on related events (@pxref{Callbacks}.) Expected type of @var{value}: an association list (alist). + +@item config +The option specifies whether an SSH config should be parsed or not, and +optionally the path to a config file. + +Setting the @var{value} to @code{#t} means that the default +@file{~/.ssh/config} should be parsed; in turn, setting the option to +@code{#f} (the default value) means that the config should not be parsed at +all. If the value is a string, then the string is expected to be a path to +config file. + +The procedure reads the config file after all other specified options are set. +When the config file is read, the options for @var{session} are set, +overwriting those that were passed to the procedure. + +You @emph{must} specify at least a host name when using this option, otherwise +the procedure will fail. + +Optionally you could use @code{session-parse-config!} procedure explicitly to +read the config (see below.) + +Expected types of @var{value}: Either a string or a boolean value. @end table @end deffn +@deffn {Scheme Procedure} session-parse-config! session [file-name] +Parse an SSH config @var{file-name} and set @var{session} options. If +@var{file-name} is not set, the default SSH @file{~/.ssh/config} is used. +Throw @code{guile-ssh-error} on an error. Return value is undefined. +@end deffn + @deffn {Scheme Procedure} session-get session option Get value of the @var{option} for @var{session}. The @var{option} is expected to be a symbol. diff --git a/libguile-ssh/session-func.c b/libguile-ssh/session-func.c index 8f4d115..86ee60a 100644 --- a/libguile-ssh/session-func.c +++ b/libguile-ssh/session-func.c @@ -464,6 +464,45 @@ Get value of the OPTION. Throw `guile-ssh-error' on an error.\ } #undef FUNC_NAME +/* Asserts: + - SESSION is a Guile-SSH session object. + - FILE_NAME either a string or '#f' */ +SCM_GSSH_DEFINE (gssh_session_parse_config, "%gssh-session-parse-config!", 2, + (SCM session, SCM file_name)) +#define FUNC_NAME s_gssh_session_parse_config +{ + struct session_data *sd = _scm_to_session_data (session); + int res; + char* c_file_name = NULL; + + SCM_ASSERT (scm_is_string (file_name) + || (scm_is_bool (file_name) && scm_is_false (file_name)), + file_name, SCM_ARG2, FUNC_NAME); + + scm_dynwind_begin (0); + + if (scm_is_string (file_name)) + { + c_file_name = scm_to_locale_string (file_name); + scm_dynwind_free (c_file_name); + } + + res = ssh_options_parse_config (sd->ssh_session, + /* 'NULL' means that we should read the + default '~/.ssh/config' file. */ + c_file_name); + if (res != SSH_OK) + { + guile_ssh_error1 (FUNC_NAME, "Could not read the configuration file", + scm_list_2 (session, file_name)); + } + + scm_dynwind_end (); + + return SCM_UNDEFINED; +} +#undef FUNC_NAME + /* Connect to the SSH server. Return one of the following symbols: 'ok, 'again, 'error diff --git a/modules/ssh/session.scm b/modules/ssh/session.scm index 912b220..96d0f91 100644 --- a/modules/ssh/session.scm +++ b/modules/ssh/session.scm @@ -27,6 +27,7 @@ ;; session? ;; %make-session ;; make-session +;; session-parse-config! ;; blocking-flush! ;; session-set! ;; session-get @@ -49,6 +50,7 @@ session? %make-session make-session + session-parse-config! blocking-flush! session-set! session-get @@ -72,7 +74,7 @@ knownhosts timeout timeout-usec ssh1 ssh2 log-verbosity ciphers-c-s ciphers-s-c compression-c-s compression-s-c proxycommand stricthostkeycheck compression - compression-level callbacks) + compression-level callbacks config) "Make a new SSH session with specified configuration.\n Return a new SSH session." (let ((session (%make-session))) @@ -97,8 +99,27 @@ Return a new SSH session." (session-set-if-specified! compression) (session-set-if-specified! compression-level) (session-set-if-specified! callbacks) + + (when config + (or host + (throw 'guile-ssh-error + "'config' is specified, but 'host' option is missed.")) + (cond + ((string? config) + (%gssh-session-parse-config! session config)) + ((boolean? config) + (%gssh-session-parse-config! session #f)) + (else + (throw 'guile-ssh-error "Wrong 'config' value" config)))) + session)) +(define* (session-parse-config! session #:optional file-name) + "Parse an SSH config FILE-NAME and set SESSION options. If FILE-NAME is not +set, the default SSH '~/.ssh/config' is used. Throw 'guile-ssh-error' on an +error. Return value is undefined." + (%gssh-session-parse-config! session file-name)) + (load-extension "libguile-ssh" "init_session") ;;; session.scm ends here diff --git a/tests/common.scm b/tests/common.scm index 56016fa..82e0e1e 100644 --- a/tests/common.scm +++ b/tests/common.scm @@ -28,6 +28,7 @@ #:export (;; Variables %topdir %knownhosts + %config %addr %rsakey %rsakey-pub @@ -70,6 +71,8 @@ (define %knownhosts (format #f "~a/tests/knownhosts" (getenv "abs_top_builddir"))) +(define %config (format #f "~a/tests/config" %topdir)) + ;; Pass the test case NAME as the userdata to the libssh log (define-syntax test-assert-with-log diff --git a/tests/config b/tests/config new file mode 100644 index 0000000..078d2f8 --- /dev/null +++ b/tests/config @@ -0,0 +1,4 @@ +Host example + Hostname example.org + Port 2222 + User alice diff --git a/tests/session.scm b/tests/session.scm index e5c054c..c436881 100644 --- a/tests/session.scm +++ b/tests/session.scm @@ -128,6 +128,14 @@ ;; Make sure that default callbacks value is '#f'. (equal? (session-get (%make-session) 'callbacks) #f)))) +(test-assert "session-parse-config!" + (let ((session (make-session #:host "example"))) + (session-parse-config! session %config) + (format (current-error-port) "session: ~a~%" session) + (and (string=? (session-get session 'host) "example.org") + (string=? (session-get session 'user) "alice") + (= (session-get session 'port) 2222)))) + (test-assert "make-session" (make-session #:host "localhost" #:port 22 |
