So the attached file works for doing pipe-based IO (like xpra needs
for ssh support) using the win32 API under Wine. But I don't have a
real Windows install to test it on.
Does anyone out there have a real Windows install, including python
and pygobject, that can test it for me?
Just save the attachment somewhere and run it: 'python win32pipe.py',
and describe what happens + send me the output.
Thanks!
-- Nathaniel
import gobject
import msvcrt
import subprocess
from ctypes import (windll, CDLL, Structure, byref, sizeof, POINTER,
c_char, c_short, c_ushort, c_int, c_uint, c_ulong,
c_void_p)
from ctypes.wintypes import HANDLE, DWORD
# This also implicitly initializes Winsock:
import socket
WSAGetLastError = windll.Ws2_32.WSAGetLastError
WSAGetLastError.argtypes = ()
WSAGetLastError.restype = c_int
SOCKET = c_int
WSASocket = windll.Ws2_32.WSASocketA
WSASocket.argtypes = (c_int, c_int, c_int, c_void_p, c_uint, DWORD)
WSASocket.restype = SOCKET
closesocket = windll.Ws2_32.closesocket
closesocket.argtypes = (SOCKET,)
closesocket.restype = c_int
class sockaddr_in(Structure):
_fields_ = [
("sin_family", c_short),
("sin_port", c_ushort),
("sin_addr", c_ulong),
("sin_zero", c_char * 8),
]
connect = windll.Ws2_32.connect
connect.argtypes = (SOCKET, c_void_p, c_int)
connect.restype = c_int
getsockname = windll.Ws2_32.getsockname
getsockname.argtypes = (SOCKET, c_void_p, POINTER(c_int))
getsockname.restype = c_int
# Returns two socket ids; first is WSASocket-compliant
def socketpair():
client = WSASocket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP,
None, 0, 0)
if client == ~0:
raise OSError, "WSASocket: %s" % (WSAGetLastError(),)
try:
listener = socket.socket()
listener.bind(("127.0.0.1", 0))
listener.listen(1)
addr = sockaddr_in()
addr.sin_family = socket.AF_INET
addr.sin_port = socket.htons(listener.getsockname()[1])
addr.sin_addr = socket.htonl(0x7f000001) # 127.0.0.1
if connect(client, byref(addr), sizeof(addr)):
raise OSError, "connect: %s" % (WSAGetLastError(),)
server, (peer_host, peer_port) = listener.accept()
assert peer_host == "127.0.0.1"
used_addr = sockaddr_in()
used_addr_size = c_int(sizeof(sockaddr_in))
if getsockname(client, byref(used_addr), byref(used_addr_size)):
raise OSError, "getsockname: %s" % (WSAGetLastError(),)
assert used_addr_size.value <= sizeof(sockaddr_in)
assert used_addr.sin_port == socket.htons(peer_port)
return (client, server.fileno(), server)
except:
closesocket(client)
raise
GIOChannel = c_void_p
class PyGIOChannel(Structure):
_fields_ = [
("HEAD", c_char * object.__basicsize__),
("channel", GIOChannel),
("softspace", c_int),
]
assert sizeof(PyGIOChannel) == gobject.IOChannel.__basicsize__
glib = CDLL("libglib-2.0-0.dll")
g_io_channel_win32_new_socket = glib.g_io_channel_win32_new_socket
g_io_channel_win32_new_socket.argtypes = (SOCKET,)
g_io_channel_win32_new_socket.restype = GIOChannel
def spawn_with_channel(cmd):
(child_sock, parent_sock, parent_pysock) = socketpair()
child_fd = msvcrt.open_osfhandle(child_sock, 0)
child = subprocess.Popen(cmd, stdin=child_fd, stdout=child_fd)
closesocket(child_sock)
channel = gobject.IOChannel.__new__(gobject.IOChannel)
channel_c = PyGIOChannel.from_address(id(channel))
channel_c.channel = g_io_channel_win32_new_socket(parent_sock)
return channel, parent_pysock
def test_spawn_with_channel():
mainloop = gobject.MainLoop()
channel, parent_pysock = spawn_with_channel(["cmd.exe"])
parent_pysock.setblocking(0)
to_write = ["dir\nexit\n"]
def event(source, flags):
if flags & gobject.IO_OUT:
print "writing"
to_write[0] = to_write[0][channel.write(to_write[0]):]
channel.flush()
print "still to write: ", to_write[0]
if flags & gobject.IO_IN:
print "Got data: %s" % channel.read(100)
elif flags & gobject.IO_HUP:
print "Connection lost"
mainloop.quit()
# Apparently on win32, the watch mysteriously disappears after every
# event!?!
flags = gobject.IO_IN | gobject.IO_HUP
if to_write[0]:
flags |= gobject.IO_OUT
channel.add_watch(flags, event)
channel.add_watch(gobject.IO_OUT | gobject.IO_IN | gobject.IO_HUP,
event)
mainloop.run()
channel.close()
if __name__ == "__main__":
test_spawn_with_channel()
_______________________________________________
Parti-discuss mailing list
[email protected]
http://lists.partiwm.org/cgi-bin/mailman/listinfo/parti-discuss