--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/pyhgsh/TODO Sun Jun 18 16:48:38 2006 -0400
@@ -0,0 +1,12 @@
+- use cmd module to provide a more powerful shell
+ (http://docs.python.org/lib/module-cmd.html)
+- command execution
+ - verify that the repository is in the list of allowed repositories
+ - make sure that we are executing 'hg serve' and nothing else
+- implement interactive commands:
+ - clone
+ - init
+ - pull
+ - push
+- convert pyhgsh.repos to format similar to hgrc
+ - use this config file to define all config options
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/pyhgsh/pyhgsh Sun Jun 18 16:48:38 2006 -0400
@@ -0,0 +1,194 @@
+#!/usr/bin/python
+#
+# pyhgsh - restricted login shell for mercurial implemented in Python
+#
+# Copyright 2006 Josef "Jeff" Sipek <jsipek@cs.sunysb.edu>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License, incorporated herein by reference.
+#
+# this program is login shell for dedicated mercurial user account. it
+# only allows few actions:
+#
+# 1. run hg in server mode on specific repository.
+#
+# 2. run interactive shell, allows for repository maintainance
+#
+# only tested on linux yet. patches for non-linux systems welcome.
+#
+
+import os
+import sys
+
+name = "pyhgsh"
+version = "0.5"
+
+prompt = "> "
+repofile= "pyhgsh.repos"
+
+repos = []
+
+def debugexit(argv, code):
+ print argv
+ sys.exit(0)
+
+def write(str):
+ sys.stdout.write(str)
+
+def valid_repo(r):
+ " returns true if r is in list of repos"
+ global repos
+
+ for okr in repos:
+ if okr == r:
+ return True
+
+ return False
+
+def cmd_help(args):
+ print name + ": The Python Mercurial shell"
+ print ""
+ print "available commands:"
+ print ""
+ for c in cmds:
+ print " %s\t%s" % (c[0], c[2])
+
+def cmd_verify(args):
+ try:
+ repo = args[0]
+ except IndexError:
+ print name + ": you must specify a valid repository"
+ return
+
+ if not valid_repo(repo):
+ print name + ": '%s' is not a valid repository" % (repo,)
+ return
+
+ os.system("hg -R %s verify" % (repo,))
+
+def cmd_repos(args):
+ for r in repos:
+ print r
+
+def cmd_quit(args):
+ sys.exit(0)
+
+def cmd_version(args):
+ print name + " (version " + version + ")"
+ os.system("hg version | head -1")
+
+def cmd_invalid(cmd):
+ print name + ": Invalid command '%s'" % (cmd,)
+
+def interactive():
+ """
+ This is an interactive shell handler
+ """
+ print ""
+ cmd_help([])
+ print ""
+
+ while True:
+ write(prompt)
+
+ try:
+ line = sys.stdin.readline()
+ tok = line.strip().split(" ")
+ except KeyboardInterrupt:
+ # ctrl-c
+ print ""
+ continue
+
+ if len(line) == 0:
+ # ctrl-d ?
+ print ""
+ cmd_quit([])
+
+ if tok[0] != "":
+ # non-empty command
+ ok = False
+ for c in cmds:
+ if tok[0] == c[0]:
+ # command found, execute
+ c[1](tok[1:])
+ ok = True
+ break
+
+ if not ok:
+ # command not found
+ cmd_invalid(tok[0])
+
+def execute(cmd):
+ """
+ Request for execution of a command handler
+ """
+
+ # this is the potentially exploitable area of the shell therefore we
+ # must make sure that everything is checked properly before we
+ # execute the command
+
+ tok = cmd.split(" ")
+
+ # it must be a hg call
+ if tok[0] != "hg":
+ print "Not a hg call"
+ return
+
+ # FIXME: hacky
+ if cmd.find(";") != -1:
+ print "Detected attept to exploit shell"
+ return
+
+ # FIXME: make sure the repo is allowed
+
+ os.system(cmd)
+
+def main(argv):
+ """
+ main, get things prepared
+ """
+
+ argv.pop(0)
+
+ # read in list of allowed repositories
+ global repos
+ f = open(repofile)
+ repos = f.readlines()
+ f.close()
+
+ for i in range(len(repos)):
+ repos[i] = repos[i].strip()
+
+ if len(argv) == 0:
+ # no args
+ interactive()
+
+ elif len(argv) == 2:
+ if argv[0] == "-c":
+ # execute command
+ execute(argv[1])
+
+ else:
+ # unknown
+ debugexit(argv, 1)
+
+ else:
+ # unkown
+ debugexit(argv, 1)
+
+# commented out commands are not implemented
+cmds = (
+# ("clone", cmd_clone, "clone a repository"),
+ ("help", cmd_help, "this screen help"),
+# ("init", cmd_init, "init a repository"),
+# ("pull", cmd_pull, "pull changes from one repository to another"),
+# ("push", cmd_push, "push changes from one repository to another"),
+ ("quit", cmd_quit, "close this session"),
+ ("repos", cmd_repos, "list repositories available"),
+ ("verify", cmd_verify, "verify a repository"),
+ ("version", cmd_version, "display version"),
+)
+
+if __name__ == "__main__":
+ main(sys.argv)
+