Package plugins :: Package core :: Package shell :: Module main
[hide private]
[frames] | no frames]

Source Code for Module plugins.core.shell.main

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov <syhpoon@syhpoon.name> 2009 
  4  # 
  5   
  6  import sys 
  7  import errno 
  8  import os 
  9  import signal 
 10   
 11  import libxyz.core as core 
 12   
 13  from libxyz.core.utils import bstring 
 14  from libxyz.core.plugins import BasePlugin 
 15   
 16  from bash import bash_setup 
 17   
18 -class XYZPlugin(BasePlugin):
19 "Shell plugin" 20 21 NAME = u"shell" 22 AUTHOR = u"Max E. Kuznecov <syhpoon@syhpoon.name>" 23 VERSION = u"0.2" 24 BRIEF_DESCRIPTION = _(u"Shell wrapper") 25 FULL_DESCRIPTION = _(u"Execute commands in external shell") 26 NAMESPACE = u"core" 27 MIN_XYZ_VERSION = None 28 DOC = u"Configuration variables:\n"\ 29 u"wait - Boolean flag indicating whether to wait for user pressing "\ 30 u"key after command executed. Default True\n"\ 31 u"setup_shell - Boolean flag indicating whether to run "\ 32 u"system shell-specific initialization. Default True" 33 34 HOMEPAGE = "http://xyzcmd.syhpoon.name" 35 EVENTS = [("execute", 36 _(u"Fires before command execution. "\ 37 u"Arguments: a command to be executed")), 38 ] 39 40 shell_args = { 41 "sh": ["-c"], 42 "bash": ["-c"], 43 "zsh": ["-c"] 44 } 45 46 shell_setup = { 47 "bash": bash_setup 48 } 49
50 - def __init__(self, xyz):
51 self.status = 0 52 self.shell = None 53 54 super(XYZPlugin, self).__init__(xyz) 55 56 self.export(self.execute) 57 self.export(self.echo)
58 59 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60
61 - def prepare(self):
62 # Determine shell 63 shell = self.xyz.conf["xyz"]["shell"] 64 _base = os.path.basename(shell) 65 66 if _base not in self.shell_args: 67 shell, _base = "/bin/sh", "sh" 68 69 self.shell = [shell] + self.shell_args[_base] 70 71 # Setup shell 72 if self.conf["setup_shell"] and _base in self.shell_setup: 73 self.shell_setup[_base](shell)
74 75 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 76
77 - def execute(self, cmd, wait=None):
78 """ 79 Execute command in shell 80 """ 81 82 cmd = bstring(cmd) 83 self.fire_event("execute", cmd) 84 85 def _exec(): 86 pid = os.fork() 87 88 # Child - Exec passed cmd 89 if pid == 0: 90 os.execvp(self.shell[0], self.shell + [cmd]) 91 # WTF? 92 sys.exit() 93 # Parent 94 else: 95 while True: 96 try: 97 self.status = os.waitpid(pid, 0) 98 except KeyboardInterrupt: 99 pass 100 except OSError, e: 101 if e.errno != errno.EINTR: 102 break 103 104 return self.status
105 106 return self._exec_engine(cmd, _exec, wait)
107 108 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 109
110 - def echo(self, msg):
111 """ 112 Echo a message to terminal output 113 """ 114 115 def _echo(): 116 print(msg)
117 118 return self._exec_engine("echo", _echo) 119 120 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 121
122 - def _press_key(self, msg, key):
123 """ 124 Print prompt and wait for the key to be pressed 125 """ 126 127 sys.stdout.write(bstring(msg)) 128 sys.stdout.flush() 129 130 while True: 131 try: 132 m = os.read(sys.stdin.fileno(), 1024) 133 if key in m: 134 break 135 except OSError, e: 136 if e.errno != errno.EINTR: 137 break
138 139 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 140
141 - def _exec_engine(self, cmd, cmdf, wait=None):
142 """ 143 Execute command engine 144 """ 145 146 self.xyz.screen.clear() 147 stdout = sys.stdout 148 self.xyz.screen.stop() 149 150 _current_term = None 151 152 # Restore original terminal settings 153 if self.xyz.term is not None: 154 _current_term = core.utils.term_settings()[-1] 155 core.utils.restore_term(self.xyz.term) 156 157 # Clear the screen 158 #TODO: make it more portable! 159 stdout.write("\x1b[H\x1b[2J") 160 161 stdout.write("%s%s\n" % 162 (bstring( 163 self.xyz.conf[u"plugins"][":sys:cmd"][u"prompt"]), 164 cmd)) 165 stdout.flush() 166 167 def _sigwinch(_a, _b): 168 self.xyz.screen.resized = True
169 170 signal.signal(signal.SIGWINCH, _sigwinch) 171 172 status = cmdf() 173 174 if _current_term is not None: 175 core.utils.restore_term(_current_term) 176 177 if wait == True or (wait != False and self.conf["wait"]): 178 self._press_key(_(u"Press ENTER to continue..."), "\n") 179 180 self.xyz.screen.start() 181 182 return status 183