Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / conch / stdio.py
1 # -*- test-case-name: twisted.conch.test.test_manhole -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 Asynchronous local terminal input handling
7
8 @author: Jp Calderone
9 """
10
11 import os, tty, sys, termios
12
13 from twisted.internet import reactor, stdio, protocol, defer
14 from twisted.python import failure, reflect, log
15
16 from twisted.conch.insults.insults import ServerProtocol
17 from twisted.conch.manhole import ColoredManhole
18
19 class UnexpectedOutputError(Exception):
20     pass
21
22 class TerminalProcessProtocol(protocol.ProcessProtocol):
23     def __init__(self, proto):
24         self.proto = proto
25         self.onConnection = defer.Deferred()
26
27     def connectionMade(self):
28         self.proto.makeConnection(self)
29         self.onConnection.callback(None)
30         self.onConnection = None
31
32     def write(self, bytes):
33         self.transport.write(bytes)
34
35     def outReceived(self, bytes):
36         self.proto.dataReceived(bytes)
37
38     def errReceived(self, bytes):
39         self.transport.loseConnection()
40         if self.proto is not None:
41             self.proto.connectionLost(failure.Failure(UnexpectedOutputError(bytes)))
42             self.proto = None
43
44     def childConnectionLost(self, childFD):
45         if self.proto is not None:
46             self.proto.childConnectionLost(childFD)
47
48     def processEnded(self, reason):
49         if self.proto is not None:
50             self.proto.connectionLost(reason)
51             self.proto = None
52
53
54
55 class ConsoleManhole(ColoredManhole):
56     """
57     A manhole protocol specifically for use with L{stdio.StandardIO}.
58     """
59     def connectionLost(self, reason):
60         """
61         When the connection is lost, there is nothing more to do.  Stop the
62         reactor so that the process can exit.
63         """
64         reactor.stop()
65
66
67
68 def runWithProtocol(klass):
69     fd = sys.__stdin__.fileno()
70     oldSettings = termios.tcgetattr(fd)
71     tty.setraw(fd)
72     try:
73         p = ServerProtocol(klass)
74         stdio.StandardIO(p)
75         reactor.run()
76     finally:
77         termios.tcsetattr(fd, termios.TCSANOW, oldSettings)
78         os.write(fd, "\r\x1bc\r")
79
80
81
82 def main(argv=None):
83     log.startLogging(file('child.log', 'w'))
84
85     if argv is None:
86         argv = sys.argv[1:]
87     if argv:
88         klass = reflect.namedClass(argv[0])
89     else:
90         klass = ConsoleManhole
91     runWithProtocol(klass)
92
93
94 if __name__ == '__main__':
95     main()