Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(466)

Side by Side Diff: third_party/twisted_8_1/twisted/conch/scripts/conch.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.conch.test.test_conch -*-
2 #
3 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6 #
7 # $Id: conch.py,v 1.65 2004/03/11 00:29:14 z3p Exp $
8
9 #""" Implementation module for the `conch` command.
10 #"""
11 from twisted.conch.client import agent, connect, default, options
12 from twisted.conch.error import ConchError
13 from twisted.conch.ssh import connection, common
14 from twisted.conch.ssh import session, forwarding, channel
15 from twisted.internet import reactor, stdio, defer, task
16 from twisted.python import log, usage
17
18 import os, sys, getpass, struct, tty, fcntl, base64, signal, stat, errno
19
20 class ClientOptions(options.ConchOptions):
21
22 synopsis = """Usage: conch [options] host [command]
23 """
24
25 optParameters = [['escape', 'e', '~'],
26 ['localforward', 'L', None, 'listen-port:host:port Forwa rd local port to remote address'],
27 ['remoteforward', 'R', None, 'listen-port:host:port Forw ard remote port to local address'],
28 ]
29
30 optFlags = [['null', 'n', 'Redirect input from /dev/null.'],
31 ['fork', 'f', 'Fork to background after authentication.'],
32 ['tty', 't', 'Tty; allocate a tty even if command is given.'],
33 ['notty', 'T', 'Do not allocate a tty.'],
34 ['noshell', 'N', 'Do not execute a shell or command.'],
35 ['subsystem', 's', 'Invoke command (mandatory) as SSH2 subsyste m.'],
36 ]
37
38 #zsh_altArgDescr = {"foo":"use this description for foo instead"}
39 #zsh_multiUse = ["foo", "bar"]
40 #zsh_mutuallyExclusive = [("foo", "bar"), ("bar", "baz")]
41 #zsh_actions = {"foo":'_files -g "*.foo"', "bar":"(one two three)"}
42 zsh_actionDescr = {"localforward":"listen-port:host:port",
43 "remoteforward":"listen-port:host:port"}
44 zsh_extras = ["*:command: "]
45
46 localForwards = []
47 remoteForwards = []
48
49 def opt_escape(self, esc):
50 "Set escape character; ``none'' = disable"
51 if esc == 'none':
52 self['escape'] = None
53 elif esc[0] == '^' and len(esc) == 2:
54 self['escape'] = chr(ord(esc[1])-64)
55 elif len(esc) == 1:
56 self['escape'] = esc
57 else:
58 sys.exit("Bad escape character '%s'." % esc)
59
60 def opt_localforward(self, f):
61 "Forward local port to remote address (lport:host:port)"
62 localPort, remoteHost, remotePort = f.split(':') # doesn't do v6 yet
63 localPort = int(localPort)
64 remotePort = int(remotePort)
65 self.localForwards.append((localPort, (remoteHost, remotePort)))
66
67 def opt_remoteforward(self, f):
68 """Forward remote port to local address (rport:host:port)"""
69 remotePort, connHost, connPort = f.split(':') # doesn't do v6 yet
70 remotePort = int(remotePort)
71 connPort = int(connPort)
72 self.remoteForwards.append((remotePort, (connHost, connPort)))
73
74 def parseArgs(self, host, *command):
75 self['host'] = host
76 self['command'] = ' '.join(command)
77
78 # Rest of code in "run"
79 options = None
80 conn = None
81 exitStatus = 0
82 old = None
83 _inRawMode = 0
84 _savedRawMode = None
85
86 def run():
87 global options, old
88 args = sys.argv[1:]
89 if '-l' in args: # cvs is an idiot
90 i = args.index('-l')
91 args = args[i:i+2]+args
92 del args[i+2:i+4]
93 for arg in args[:]:
94 try:
95 i = args.index(arg)
96 if arg[:2] == '-o' and args[i+1][0]!='-':
97 args[i:i+2] = [] # suck on it scp
98 except ValueError:
99 pass
100 options = ClientOptions()
101 try:
102 options.parseOptions(args)
103 except usage.UsageError, u:
104 print 'ERROR: %s' % u
105 options.opt_help()
106 sys.exit(1)
107 if options['log']:
108 if options['logfile']:
109 if options['logfile'] == '-':
110 f = sys.stdout
111 else:
112 f = file(options['logfile'], 'a+')
113 else:
114 f = sys.stderr
115 realout = sys.stdout
116 log.startLogging(f)
117 sys.stdout = realout
118 else:
119 log.discardLogs()
120 doConnect()
121 fd = sys.stdin.fileno()
122 try:
123 old = tty.tcgetattr(fd)
124 except:
125 old = None
126 try:
127 oldUSR1 = signal.signal(signal.SIGUSR1, lambda *a: reactor.callLater(0, reConnect))
128 except:
129 oldUSR1 = None
130 try:
131 reactor.run()
132 finally:
133 if old:
134 tty.tcsetattr(fd, tty.TCSANOW, old)
135 if oldUSR1:
136 signal.signal(signal.SIGUSR1, oldUSR1)
137 if (options['command'] and options['tty']) or not options['notty']:
138 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
139 if sys.stdout.isatty() and not options['command']:
140 print 'Connection to %s closed.' % options['host']
141 sys.exit(exitStatus)
142
143 def handleError():
144 from twisted.python import failure
145 global exitStatus
146 exitStatus = 2
147 reactor.callLater(0.01, _stopReactor)
148 log.err(failure.Failure())
149 raise
150
151 def _stopReactor():
152 try:
153 reactor.stop()
154 except: pass
155
156 def doConnect():
157 # log.deferr = handleError # HACK
158 if '@' in options['host']:
159 options['user'], options['host'] = options['host'].split('@',1)
160 if not options.identitys:
161 options.identitys = ['~/.ssh/id_rsa', '~/.ssh/id_dsa']
162 host = options['host']
163 if not options['user']:
164 options['user'] = getpass.getuser()
165 if not options['port']:
166 options['port'] = 22
167 else:
168 options['port'] = int(options['port'])
169 host = options['host']
170 port = options['port']
171 vhk = default.verifyHostKey
172 uao = default.SSHUserAuthClient(options['user'], options, SSHConnection())
173 connect.connect(host, port, options, vhk, uao).addErrback(_ebExit)
174
175 def _ebExit(f):
176 global exitStatus
177 if hasattr(f.value, 'value'):
178 s = f.value.value
179 else:
180 s = str(f)
181 exitStatus = "conch: exiting with error %s" % f
182 reactor.callLater(0.1, _stopReactor)
183
184 def onConnect():
185 # if keyAgent and options['agent']:
186 # cc = protocol.ClientCreator(reactor, SSHAgentForwardingLocal, conn)
187 # cc.connectUNIX(os.environ['SSH_AUTH_SOCK'])
188 if hasattr(conn.transport, 'sendIgnore'):
189 _KeepAlive(conn)
190 if options.localForwards:
191 for localPort, hostport in options.localForwards:
192 s = reactor.listenTCP(localPort,
193 forwarding.SSHListenForwardingFactory(conn,
194 hostport,
195 SSHListenClientForwardingChannel))
196 conn.localForwards.append(s)
197 if options.remoteForwards:
198 for remotePort, hostport in options.remoteForwards:
199 log.msg('asking for remote forwarding for %s:%s' %
200 (remotePort, hostport))
201 conn.requestRemoteForwarding(remotePort, hostport)
202 reactor.addSystemEventTrigger('before', 'shutdown', beforeShutdown)
203 if not options['noshell'] or options['agent']:
204 conn.openChannel(SSHSession())
205 if options['fork']:
206 if os.fork():
207 os._exit(0)
208 os.setsid()
209 for i in range(3):
210 try:
211 os.close(i)
212 except OSError, e:
213 import errno
214 if e.errno != errno.EBADF:
215 raise
216
217 def reConnect():
218 beforeShutdown()
219 conn.transport.transport.loseConnection()
220
221 def beforeShutdown():
222 remoteForwards = options.remoteForwards
223 for remotePort, hostport in remoteForwards:
224 log.msg('cancelling %s:%s' % (remotePort, hostport))
225 conn.cancelRemoteForwarding(remotePort)
226
227 def stopConnection():
228 if not options['reconnect']:
229 reactor.callLater(0.1, _stopReactor)
230
231 class _KeepAlive:
232
233 def __init__(self, conn):
234 self.conn = conn
235 self.globalTimeout = None
236 self.lc = task.LoopingCall(self.sendGlobal)
237 self.lc.start(300)
238
239 def sendGlobal(self):
240 d = self.conn.sendGlobalRequest("conch-keep-alive@twistedmatrix.com",
241 "", wantReply = 1)
242 d.addBoth(self._cbGlobal)
243 self.globalTimeout = reactor.callLater(30, self._ebGlobal)
244
245 def _cbGlobal(self, res):
246 if self.globalTimeout:
247 self.globalTimeout.cancel()
248 self.globalTimeout = None
249
250 def _ebGlobal(self):
251 if self.globalTimeout:
252 self.globalTimeout = None
253 self.conn.transport.loseConnection()
254
255 class SSHConnection(connection.SSHConnection):
256 def serviceStarted(self):
257 global conn
258 conn = self
259 self.localForwards = []
260 self.remoteForwards = {}
261 if not isinstance(self, connection.SSHConnection):
262 # make these fall through
263 del self.__class__.requestRemoteForwarding
264 del self.__class__.cancelRemoteForwarding
265 onConnect()
266
267 def serviceStopped(self):
268 lf = self.localForwards
269 self.localForwards = []
270 for s in lf:
271 s.loseConnection()
272 stopConnection()
273
274 def requestRemoteForwarding(self, remotePort, hostport):
275 data = forwarding.packGlobal_tcpip_forward(('0.0.0.0', remotePort))
276 d = self.sendGlobalRequest('tcpip-forward', data,
277 wantReply=1)
278 log.msg('requesting remote forwarding %s:%s' %(remotePort, hostport))
279 d.addCallback(self._cbRemoteForwarding, remotePort, hostport)
280 d.addErrback(self._ebRemoteForwarding, remotePort, hostport)
281
282 def _cbRemoteForwarding(self, result, remotePort, hostport):
283 log.msg('accepted remote forwarding %s:%s' % (remotePort, hostport))
284 self.remoteForwards[remotePort] = hostport
285 log.msg(repr(self.remoteForwards))
286
287 def _ebRemoteForwarding(self, f, remotePort, hostport):
288 log.msg('remote forwarding %s:%s failed' % (remotePort, hostport))
289 log.msg(f)
290
291 def cancelRemoteForwarding(self, remotePort):
292 data = forwarding.packGlobal_tcpip_forward(('0.0.0.0', remotePort))
293 self.sendGlobalRequest('cancel-tcpip-forward', data)
294 log.msg('cancelling remote forwarding %s' % remotePort)
295 try:
296 del self.remoteForwards[remotePort]
297 except:
298 pass
299 log.msg(repr(self.remoteForwards))
300
301 def channel_forwarded_tcpip(self, windowSize, maxPacket, data):
302 log.msg('%s %s' % ('FTCP', repr(data)))
303 remoteHP, origHP = forwarding.unpackOpen_forwarded_tcpip(data)
304 log.msg(self.remoteForwards)
305 log.msg(remoteHP)
306 if self.remoteForwards.has_key(remoteHP[1]):
307 connectHP = self.remoteForwards[remoteHP[1]]
308 log.msg('connect forwarding %s' % (connectHP,))
309 return SSHConnectForwardingChannel(connectHP,
310 remoteWindow = windowSize,
311 remoteMaxPacket = maxPacket,
312 conn = self)
313 else:
314 raise ConchError(connection.OPEN_CONNECT_FAILED, "don't know about t hat port")
315
316 # def channel_auth_agent_openssh_com(self, windowSize, maxPacket, data):
317 # if options['agent'] and keyAgent:
318 # return agent.SSHAgentForwardingChannel(remoteWindow = windowSize,
319 # remoteMaxPacket = maxPacket,
320 # conn = self)
321 # else:
322 # return connection.OPEN_CONNECT_FAILED, "don't have an agent"
323
324 def channelClosed(self, channel):
325 log.msg('connection closing %s' % channel)
326 log.msg(self.channels)
327 if len(self.channels) == 1 and not (options['noshell'] and not options[' nocache']): # just us left
328 log.msg('stopping connection')
329 stopConnection()
330 else:
331 # because of the unix thing
332 self.__class__.__bases__[0].channelClosed(self, channel)
333
334 class SSHSession(channel.SSHChannel):
335
336 name = 'session'
337
338 def channelOpen(self, foo):
339 log.msg('session %s open' % self.id)
340 if options['agent']:
341 d = self.conn.sendRequest(self, 'auth-agent-req@openssh.com', '', wa ntReply=1)
342 d.addBoth(lambda x:log.msg(x))
343 if options['noshell']: return
344 if (options['command'] and options['tty']) or not options['notty']:
345 _enterRawMode()
346 c = session.SSHSessionClient()
347 if options['escape'] and not options['notty']:
348 self.escapeMode = 1
349 c.dataReceived = self.handleInput
350 else:
351 c.dataReceived = self.write
352 c.connectionLost = lambda x=None,s=self:s.sendEOF()
353 self.stdio = stdio.StandardIO(c)
354 fd = 0
355 if options['subsystem']:
356 self.conn.sendRequest(self, 'subsystem', \
357 common.NS(options['command']))
358 elif options['command']:
359 if options['tty']:
360 term = os.environ['TERM']
361 winsz = fcntl.ioctl(fd, tty.TIOCGWINSZ, '12345678')
362 winSize = struct.unpack('4H', winsz)
363 ptyReqData = session.packRequest_pty_req(term, winSize, '')
364 self.conn.sendRequest(self, 'pty-req', ptyReqData)
365 signal.signal(signal.SIGWINCH, self._windowResized)
366 self.conn.sendRequest(self, 'exec', \
367 common.NS(options['command']))
368 else:
369 if not options['notty']:
370 term = os.environ['TERM']
371 winsz = fcntl.ioctl(fd, tty.TIOCGWINSZ, '12345678')
372 winSize = struct.unpack('4H', winsz)
373 ptyReqData = session.packRequest_pty_req(term, winSize, '')
374 self.conn.sendRequest(self, 'pty-req', ptyReqData)
375 signal.signal(signal.SIGWINCH, self._windowResized)
376 self.conn.sendRequest(self, 'shell', '')
377 #if hasattr(conn.transport, 'transport'):
378 # conn.transport.transport.setTcpNoDelay(1)
379
380 def handleInput(self, char):
381 #log.msg('handling %s' % repr(char))
382 if char in ('\n', '\r'):
383 self.escapeMode = 1
384 self.write(char)
385 elif self.escapeMode == 1 and char == options['escape']:
386 self.escapeMode = 2
387 elif self.escapeMode == 2:
388 self.escapeMode = 1 # so we can chain escapes together
389 if char == '.': # disconnect
390 log.msg('disconnecting from escape')
391 stopConnection()
392 return
393 elif char == '\x1a': # ^Z, suspend
394 def _():
395 _leaveRawMode()
396 sys.stdout.flush()
397 sys.stdin.flush()
398 os.kill(os.getpid(), signal.SIGTSTP)
399 _enterRawMode()
400 reactor.callLater(0, _)
401 return
402 elif char == 'R': # rekey connection
403 log.msg('rekeying connection')
404 self.conn.transport.sendKexInit()
405 return
406 elif char == '#': # display connections
407 self.stdio.write('\r\nThe following connections are open:\r\n')
408 channels = self.conn.channels.keys()
409 channels.sort()
410 for channelId in channels:
411 self.stdio.write(' #%i %s\r\n' % (channelId, str(self.conn. channels[channelId])))
412 return
413 self.write('~' + char)
414 else:
415 self.escapeMode = 0
416 self.write(char)
417
418 def dataReceived(self, data):
419 self.stdio.write(data)
420
421 def extReceived(self, t, data):
422 if t==connection.EXTENDED_DATA_STDERR:
423 log.msg('got %s stderr data' % len(data))
424 sys.stderr.write(data)
425
426 def eofReceived(self):
427 log.msg('got eof')
428 self.stdio.closeStdin()
429
430 def closeReceived(self):
431 log.msg('remote side closed %s' % self)
432 self.conn.sendClose(self)
433
434 def closed(self):
435 global old
436 log.msg('closed %s' % self)
437 log.msg(repr(self.conn.channels))
438 if not options['nocache']: # fork into the background
439 if os.fork():
440 if old:
441 fd = sys.stdin.fileno()
442 tty.tcsetattr(fd, tty.TCSANOW, old)
443 if (options['command'] and options['tty']) or \
444 not options['notty']:
445 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
446 os._exit(0)
447 os.setsid()
448 for i in range(3):
449 try:
450 os.close(i)
451 except OSError, e:
452 import errno
453 if e.errno != errno.EBADF:
454 raise
455
456 def request_exit_status(self, data):
457 global exitStatus
458 exitStatus = int(struct.unpack('>L', data)[0])
459 log.msg('exit status: %s' % exitStatus)
460
461 def sendEOF(self):
462 self.conn.sendEOF(self)
463
464 def stopWriting(self):
465 self.stdio.pauseProducing()
466
467 def startWriting(self):
468 self.stdio.resumeProducing()
469
470 def _windowResized(self, *args):
471 winsz = fcntl.ioctl(0, tty.TIOCGWINSZ, '12345678')
472 winSize = struct.unpack('4H', winsz)
473 newSize = winSize[1], winSize[0], winSize[2], winSize[3]
474 self.conn.sendRequest(self, 'window-change', struct.pack('!4L', *newSize ))
475
476
477 class SSHListenClientForwardingChannel(forwarding.SSHListenClientForwardingChann el): pass
478 class SSHConnectForwardingChannel(forwarding.SSHConnectForwardingChannel): pass
479
480 def _leaveRawMode():
481 global _inRawMode
482 if not _inRawMode:
483 return
484 fd = sys.stdin.fileno()
485 tty.tcsetattr(fd, tty.TCSANOW, _savedMode)
486 _inRawMode = 0
487
488 def _enterRawMode():
489 global _inRawMode, _savedMode
490 if _inRawMode:
491 return
492 fd = sys.stdin.fileno()
493 try:
494 old = tty.tcgetattr(fd)
495 new = old[:]
496 except:
497 log.msg('not a typewriter!')
498 else:
499 # iflage
500 new[0] = new[0] | tty.IGNPAR
501 new[0] = new[0] & ~(tty.ISTRIP | tty.INLCR | tty.IGNCR | tty.ICRNL |
502 tty.IXON | tty.IXANY | tty.IXOFF)
503 if hasattr(tty, 'IUCLC'):
504 new[0] = new[0] & ~tty.IUCLC
505
506 # lflag
507 new[3] = new[3] & ~(tty.ISIG | tty.ICANON | tty.ECHO | tty.ECHO |
508 tty.ECHOE | tty.ECHOK | tty.ECHONL)
509 if hasattr(tty, 'IEXTEN'):
510 new[3] = new[3] & ~tty.IEXTEN
511
512 #oflag
513 new[1] = new[1] & ~tty.OPOST
514
515 new[6][tty.VMIN] = 1
516 new[6][tty.VTIME] = 0
517
518 _savedMode = old
519 tty.tcsetattr(fd, tty.TCSANOW, new)
520 #tty.setraw(fd)
521 _inRawMode = 1
522
523 if __name__ == '__main__':
524 run()
525
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/conch/scripts/ckeygen.py ('k') | third_party/twisted_8_1/twisted/conch/scripts/tkconch.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698