api-popen.texi 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. @c -*-texinfo-*-
  2. @c This file is part of Guile-SSH Reference Manual.
  3. @c Copyright (C) 2015 Artyom V. Poptsov
  4. @c See the file guile-ssh.texi for copying conditions.
  5. @node Remote Pipes
  6. @section Remote Pipes
  7. @cindex remote pipes
  8. @code{(ssh popen)} provides API for working with remote pipes, akin to
  9. @code{(ice-9 popen)} procedures (@pxref{Pipes,,, guile, The GNU Guile
  10. Reference Manual})
  11. @var{mode} argument allows to specify what kind of pipe should be created.
  12. Allowed values are: @code{OPEN_READ}, @code{OPEN_WRITE}, @code{OPEN_BOTH}.
  13. There is an additional value, @code{OPEN_PTY}, that allows to request a pseudo
  14. terminal. The terminal is needed to run such commands as @code{top}. Thus,
  15. to run @code{top} on the remote side you need to open a remote pipe with "t"
  16. flag set.
  17. @strong{Note} that when a PTY is used, a server merges stderr stream with
  18. stdout.
  19. Values of the aforementioned constants:
  20. @table @samp
  21. @item OPEN_READ
  22. ``r''
  23. @item OPEN_WRITE
  24. ``w''
  25. @item OPEN_BOTH
  26. ``r+''
  27. @item OPEN_PTY
  28. ``t''
  29. @end table
  30. @deffn {Scheme Procedure} open-remote-pipe session command mode
  31. Execute a @var{command} on the remote host using a @var{session} with a pipe
  32. to it. Returns newly created channel port with the specified @var{mode}.
  33. @end deffn
  34. @deffn {Scheme Procedure} open-remote-pipe* session mode prog [args...]
  35. Execute @var{prog} on the remote host with the given @var{args} using a
  36. @var{session} with a pipe to it. Returns newly created channel port with the
  37. specified @var{mode}.
  38. @end deffn
  39. @deffn {Scheme Procedure} open-remote-input-pipe session command
  40. @deffnx {Scheme Procedure} open-remote-input-pipe* session prog [args...]
  41. Equvalent to @code{open-remote-pipe} and @code{open-remote-pipe*} respectively
  42. with mode @code{OPEN_READ}.
  43. @end deffn
  44. @deffn {Scheme Procedure} open-remote-output-pipe session command
  45. @deffnx {Scheme Procedure} open-remote-output-pipe* session prog [args...]
  46. Equvalent to @code{open-remote-pipe} and @code{open-remote-pipe*} respectively
  47. with mode @code{OPEN_WRITE}.
  48. @end deffn
  49. @subsection Examples
  50. @subsubsection Simple cases
  51. Here's a self-explanatory little script that executes @code{uname -o} command
  52. on the local host and prints the result:
  53. @lisp
  54. #!/usr/bin/guile \
  55. -e main -s
  56. !#
  57. (use-modules (ice-9 rdelim) ; @{read,write@}-line
  58. ;; Guile-SSH
  59. (ssh session)
  60. (ssh auth)
  61. (ssh popen)) ; remote pipes
  62. (define (main args)
  63. ;; Make a session with local machine and the current user.
  64. (let ((session (make-session #:host "localhost")))
  65. ;; Connect the session and perform the authentication.
  66. (connect! session)
  67. (authenticate-server session)
  68. (userauth-agent! session)
  69. ;; Execute the command on the remote side and get the input pipe
  70. ;; to it.
  71. (let ((channel (open-remote-input-pipe session "uname -o")))
  72. ;; Read and display the result.
  73. (write-line (read-line channel)))))
  74. @end lisp
  75. @subsubsection Executing a command with a pseudo terminal
  76. Surely we aren't limited to one-line outputs; for example, we can watch
  77. @code{top} command executing on a remote side locally, by reading data from
  78. the channel in a loop:
  79. @lisp
  80. (define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
  81. (let ((channel (open-remote-pipe* session OPEN_PTY_READ
  82. "top" "-u avp")))
  83. (let r ((line (read-line channel)))
  84. (unless (eof-object? line)
  85. (write-line line)
  86. (r (read-line channel)))))
  87. @end lisp
  88. Or we can do the same, but this time with streams:
  89. @lisp
  90. (use-modules (srfi srfi-41) ; streams
  91. (ssh session)
  92. (ssh auth)
  93. (ssh popen))
  94. (define (pipe->stream p)
  95. (stream-let loop ((c (read-char p)))
  96. (if (eof-object? c)
  97. (begin
  98. (close-input-port p)
  99. stream-null)
  100. (stream-cons c (loop (read-char p))))))
  101. (define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
  102. (define (main args)
  103. (let ((s (make-session #:host "example.org")))
  104. (connect! s)
  105. (userauth-agent! s)
  106. (let ((rs (pipe->stream (open-remote-pipe* s OPEN_PTY_READ
  107. "top" "-u avp"))))
  108. (stream-for-each display rs))))
  109. @end lisp
  110. @subsubsection Controlling the pseudo terminal size
  111. To set the size of a pseudo terminal, one may use @code{channel-set-pty-size!}
  112. from @code{(ssh channel)}. For example:
  113. @lisp
  114. (use-modules (ssh popen)
  115. (ssh auth)
  116. (ssh channel))
  117. (define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
  118. ;; Opening of a Guile-SSH session goes here ...
  119. (let ((p (open-remote-pipe* session OPEN_PTY_READ "top" "-u avp")))
  120. (channel-set-pty-size! p 80 50)
  121. ;; Reading output from a port ...
  122. )
  123. @end lisp
  124. @c Local Variables:
  125. @c TeX-master: "guile-ssh.texi"
  126. @c End: