1#!/usr/bin/env python
2
3##############################################
4# Console client for Xen guest OSes
5# Copyright (c) 2004, K A Fraser
6##############################################
7
8import errno, os, signal, socket, struct, sys
9
10from termios import *
11# Indexes into termios.tcgetattr() list.
12IFLAG  = 0
13OFLAG  = 1
14CFLAG  = 2
15LFLAG  = 3
16ISPEED = 4
17OSPEED = 5
18CC     = 6
19
20def __child_death(signum, frame):
21    global stop
22    stop = True
23
24def __recv_from_sock(sock):
25    global stop
26    stop = False
27    while not stop:
28        try:
29            data = sock.recv(1024)
30        except socket.error, error:
31            if error[0] != errno.EINTR:
32                raise
33        else:
34            try:
35                os.write(1, data)
36            except os.error, error:
37                if error[0] != errno.EINTR:
38                    raise
39    os.wait()
40
41def __send_to_sock(sock):
42    while 1:
43        try:
44            data = os.read(0,1024)
45        except os.error, error:
46            if error[0] != errno.EINTR:
47                raise
48        else:
49            if ord(data[0]) == ord(']')-64:
50                break
51            try:
52                sock.send(data)
53            except socket.error, error:
54                if error[0] == errno.EPIPE:
55                    sys.exit(0)
56                if error[0] != errno.EINTR:
57                    raise
58    sys.exit(0)
59
60def connect(host,port):
61    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
62    sock.connect((host,port))
63
64    oattrs = tcgetattr(0)
65    nattrs = tcgetattr(0)
66    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
67    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
68    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
69    nattrs[CFLAG] = nattrs[CFLAG] | CS8
70    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
71    nattrs[CC][VMIN] = 1
72    nattrs[CC][VTIME] = 0
73
74    if os.fork():
75        signal.signal(signal.SIGCHLD, __child_death)
76        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
77        tcsetattr(0, TCSAFLUSH, nattrs)
78        try:
79            __recv_from_sock(sock)
80        finally:
81            tcsetattr(0, TCSAFLUSH, oattrs)
82            print
83            print "************ REMOTE CONSOLE EXITED *****************"
84    else:
85        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
86        __send_to_sock(sock)
87
88if __name__ == '__main__':
89    if len(sys.argv) != 3:
90        print sys.argv[0] + " <host> <port>"
91        sys.exit(1)
92    connect(str(sys.argv[1]),int(sys.argv[2]))
93