Skip to content

Instantly share code, notes, and snippets.

@artyom-poptsov
Last active February 22, 2016 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artyom-poptsov/d8772f3085213398e49c to your computer and use it in GitHub Desktop.
Save artyom-poptsov/d8772f3085213398e49c to your computer and use it in GitHub Desktop.
Run 'top' command on a remote side using Guile-SSH remote pipes, show the output of 'top' in uppercase letters.
#!/usr/bin/guile \
-e main -s
!#
;;; uptop.scm -- Uppercase top.
;; Copyright (C) 2016 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:
;; The program is known to work on the Guile-SSH 'master' branch, commit
;; 2ab0287.
;;; Code:
(use-modules (srfi srfi-41) ; streams
(ssh session)
(ssh auth)
(ssh popen) ; remote pipes
(ssh channel)) ; channel-set-pty!
(define (pipe->stream p)
"Convert a pipe P to a SRFI-41 stream."
(stream-let loop ((c (read-char p)))
(if (eof-object? c)
(begin
(close-input-port p)
stream-null)
(stream-cons c (loop (read-char p))))))
(define (open-remote-input-pipe/pty* session command . args)
"Open remote input pipe with PTY, run a COMMAND with ARGS."
(define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
(let ((p (apply open-remote-pipe* session OPEN_PTY_READ command args)))
(channel-set-pty-size! p 80 40)
p))
(define char-upcase/skip-esc
(let ((state 'regular-char))
(lambda (chr)
"Return the uppercase character version of a CHR, skip therminal escape
sequences."
(cond
((char=? chr (integer->char 27))
(set! state 'escape-sequence)
chr)
((char=? chr #\m)
(if (equal? state 'escape-sequence)
(begin
(set! state 'regular-char)
chr)
(char-upcase chr)))
(else
(char-upcase chr))))))
;;;
(define (main args)
"Entry point."
(let ((s (make-session #:host "example.org")))
(connect! s)
(userauth-agent! s)
(let ((rs (pipe->stream (open-remote-input-pipe/pty* s "top" "-u $USER"))))
(stream-for-each display (stream-map char-upcase/skip-esc rs)))))
;;; uptop.scm ends here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment