| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import os | |
| 6 import subprocess | |
| 7 import struct | |
| 8 import sys | |
| 9 | |
| 10 import naclimc | |
| 11 | |
| 12 | |
| 13 # Descriptor for a bound socket that the NaCl browser plugin sets up | |
| 14 NACL_PLUGIN_BOUND_SOCK = 3 | |
| 15 | |
| 16 # Descriptors for connected sockets that the NaCl browser plugin sets up | |
| 17 NACL_PLUGIN_ASYNC_FROM_CHILD_FD = 6 | |
| 18 NACL_PLUGIN_ASYNC_TO_CHILD_FD = 7 | |
| 19 | |
| 20 | |
| 21 def PackStringList(strings): | |
| 22 return "".join(arg + "\0" for arg in strings) | |
| 23 | |
| 24 | |
| 25 def PackArgsMessage(argv, envv): | |
| 26 return (struct.pack("4sII", "ARGS", len(argv), len(envv)) | |
| 27 + PackStringList(argv) | |
| 28 + PackStringList(envv)) | |
| 29 | |
| 30 | |
| 31 def SpawnSelLdrWithSockets(args, fd_slots, **kwargs): | |
| 32 sockets = [(fd_slot, naclimc.os_socketpair()) | |
| 33 for fd_slot in fd_slots] | |
| 34 extra_args = [] | |
| 35 for fd_slot, (child_fd, parent_fd) in sockets: | |
| 36 extra_args.extend(["-i", "%i:%i" % (fd_slot, child_fd)]) | |
| 37 | |
| 38 def PreExec(): | |
| 39 for fd_slot, (child_fd, parent_fd) in sockets: | |
| 40 os.close(parent_fd) | |
| 41 | |
| 42 cmd = [os.environ["NACL_SEL_LDR"]] + extra_args + args | |
| 43 proc = subprocess.Popen(cmd, preexec_fn=PreExec, **kwargs) | |
| 44 for fd_slot, (child_fd, parent_fd) in sockets: | |
| 45 os.close(child_fd) | |
| 46 result_sockets = [naclimc.from_os_socket(parent_fd) | |
| 47 for fd_slot, (child_fd, parent_fd) in sockets] | |
| 48 return proc, result_sockets | |
| 49 | |
| 50 | |
| 51 def FileServer(recv_socket, send_socket): | |
| 52 while True: | |
| 53 try: | |
| 54 message, fds = recv_socket.imc_recvmsg(1024) | |
| 55 # TODO(mseaborn): When the Python bindings raise a specific | |
| 56 # exception type, we should test for that for EOF instead. | |
| 57 except Exception: | |
| 58 break | |
| 59 method_id = message[:4] | |
| 60 message_body = message[4:] | |
| 61 if method_id == "Open": | |
| 62 # TODO(mseaborn): When we handle more types of request, we can | |
| 63 # factor out the unmarshalling code. | |
| 64 format = "ii" | |
| 65 flags, mode = struct.unpack_from(format, message_body) | |
| 66 filename = message_body[struct.calcsize(format):] | |
| 67 try: | |
| 68 fd = os.open(filename, flags) | |
| 69 except OSError: | |
| 70 send_socket.imc_sendmsg("Fail", tuple([])) | |
| 71 else: | |
| 72 desc = naclimc.from_os_file_descriptor(fd) | |
| 73 send_socket.imc_sendmsg("Okay", tuple([desc])) | |
| 74 | |
| 75 | |
| 76 def Main(args): | |
| 77 lib_dir = os.environ["NACL_LIBRARY_DIR"] | |
| 78 sel_ldr_args = [ | |
| 79 # TODO(mseaborn): Fix validation errors so that we do not need | |
| 80 # to use -s (stubout mode) with nacl-glibc. | |
| 81 "-s", | |
| 82 "--", os.path.join(lib_dir, "runnable-ld.so")] | |
| 83 proc, [fd1, recv_socket, send_socket] = SpawnSelLdrWithSockets( | |
| 84 sel_ldr_args, | |
| 85 [NACL_PLUGIN_BOUND_SOCK, | |
| 86 NACL_PLUGIN_ASYNC_FROM_CHILD_FD, | |
| 87 NACL_PLUGIN_ASYNC_TO_CHILD_FD]) | |
| 88 argv = ["unused-argv0", "--library-path", lib_dir] + args | |
| 89 envv = ["NACL_FILE_RPC=1"] | |
| 90 send_socket.imc_sendmsg(PackArgsMessage(argv, envv), tuple([])) | |
| 91 FileServer(recv_socket, send_socket) | |
| 92 sys.exit(proc.wait()) | |
| 93 | |
| 94 | |
| 95 if __name__ == "__main__": | |
| 96 Main(sys.argv[1:]) | |
| OLD | NEW |