Skip to Content.
Sympa Menu

grouper-dev - [grouper-dev] GSH readline support on *NIX

Subject: Grouper Developers Forum

List archive

[grouper-dev] GSH readline support on *NIX


Chronological Thread 
  • From: Carl Waldbieser <>
  • To:
  • Subject: [grouper-dev] GSH readline support on *NIX
  • Date: Thu, 28 Aug 2014 22:32:00 -0400

I've just started experimenting with Grouper.  I used the Grouper installer and have started watching the various admin tutorials.

One thing I noticed right away is that the `gsh` shell seems to be a bit lacking in interactive mode.  There is no command history, nor can I use the arrow keys to move on the command line and make edits.

I am guessing something like rlwrap would work to add readline support to this command on man Linux environments.  The server I am testing on is RHEL6, and didn't have that package, so I put together a quick Python script that does the same thing.

I have attached the script as 'gsh_plus.py'.  You basically put it in the same folder as gsh and you run "$GROUPER_HOME/bin/gsh_plus.py" instead of gsh.  Almost magically, you will have command line history and the use of arrow keys (if your system Python has readline support).

It is a bit dodgy about overwriting the prompts if you scroll through the history to a blank line, but I find the benefits outweigh this issue, at least until gsh grows its own readline support (hopefully with tab-completion?).

Thanks,
Carl Waldbieser
System Programmer
Lafayette College

#! /usr/bin/env python


import cmd
import os
import os.path
import pty
import re
import sys
from threading  import Thread


class MyCmd(cmd.Cmd):
    """
    """
    def __init__(self):
        cmd.Cmd.__init__(self)
        self.prompt = ""
        pid, fd = pty.fork()
        if pid == 0:
            pth = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gsh')
            sys_shell = os.environ.get("SHELL", '/bin/sh')
            sys.stdout.flush()
            os.execl(sys_shell, sys_shell, pth)
        else:
            self.child_pid = pid
            self.pty_fd = fd
            t = Thread(target=self.printer)
            t.daemon = True
            t.start()

    def printer(self):
        pat = re.compile(r"^gsh \d+%")
        stdout = sys.stdout
        fd = self.pty_fd
        lines = []
        leading = ''
        while True:
            chunk = os.read(fd, 1024)
            if chunk != "":
                lines.extend(("%s%s" % (leading, chunk)).split('\n'))
                leading = ''

            line_count = len(lines)
            while line_count > 0:
                line = lines[0]
                lines = lines[1:]
                line_count -= 1
                if line_count > 0:
                    stdout.write(line)
                    stdout.write('\n')
                else:
                    m = pat.search(line)
                    if m is None:
                        leading = line
                    else:
                        stdout.write(line)
            
            stdout.flush()
        

    def do_EOF(self, line):
        print
        return True

    def do_help(self, line):
        self.default('help%s' % line)

    def emptyline(self):
        self.default('')

    def default(self, line):
        """
        """
        fd = self.pty_fd
        os.write(fd, line + '\n')

def my_repl():
    """
    """
    cmd = MyCmd()
    cmd.cmdloop()
    

if __name__ == "__main__":
    my_repl()



Archive powered by MHonArc 2.6.16.

Top of Page