| 36 | |
| 37 | |
| 38 | class Runner: |
| 39 | def __init__(self, argv, logfunc, promptfunc, serverobj): |
| 40 | print 'in __init__' |
| 41 | self.id = argv |
| 42 | self.rv = None |
| 43 | self.pid = None |
| 44 | self.fd = None |
| 45 | self.logfunc = logfunc |
| 46 | self.promptfunc = promptfunc |
| 47 | self.serverobj = serverobj |
| 48 | self.buf = '' |
| 49 | self.logfunc('\nConnecting to %s.\n' % self.serverobj.host()) |
| 50 | print 'will run: %r' % argv |
| 51 | self.serverobj.setConnected_(False) |
| 52 | pid,fd = pty.fork() |
| 53 | if pid == 0: |
| 54 | # child |
| 55 | try: |
| 56 | os.execvp(argv[0], argv) |
| 57 | except Exception, e: |
| 58 | sys.stderr.write('failed to start: %r\n' % e) |
| 59 | raise |
| 60 | finally: |
| 61 | os._exit(42) |
| 62 | # parent |
| 63 | self.pid = pid |
| 64 | self.file = NSFileHandle.alloc()\ |
| 65 | .initWithFileDescriptor_closeOnDealloc_(fd, True) |
| 66 | self.cb = Callback(self.gotdata) |
| 67 | NSNotificationCenter.defaultCenter()\ |
| 68 | .addObserver_selector_name_object_(self.cb.obj, self.cb.sel, |
| 69 | NSFileHandleDataAvailableNotification, self.file) |
| 70 | self.file.waitForDataInBackgroundAndNotify() |
| 71 | |
| 72 | def __del__(self): |
| 73 | self.wait() |
| 74 | |
| 75 | def _try_wait(self, options): |
| 76 | if self.rv == None and self.pid > 0: |
| 77 | pid,code = os.waitpid(self.pid, options) |
| 78 | if pid == self.pid: |
| 79 | if os.WIFEXITED(code): |
| 80 | self.rv = os.WEXITSTATUS(code) |
| 81 | if self.rv == 111: |
| 82 | NSRunAlertPanel('Sshuttle', |
| 83 | 'Please restart your computer to finish ' |
| 84 | 'installing Sshuttle.', |
| 85 | 'Restart Later', None, None) |
| 86 | else: |
| 87 | self.rv = -os.WSTOPSIG(code) |
| 88 | self.serverobj.setConnected_(False) |
| 89 | self.serverobj.setError_('VPN process died') |
| 90 | self.logfunc('Disconnected.\n') |
| 91 | print 'wait_result: %r' % self.rv |
| 92 | return self.rv |
| 93 | |
| 94 | def wait(self): |
| 95 | rv = None |