@@ -89,12 +89,10 @@ cdef class Channel:
89
89
def poll (self , timeout = - 1 , stderr = 0 ):
90
90
if timeout < 0 :
91
91
rc = libssh.ssh_channel_poll(self ._libssh_channel, stderr)
92
- if rc == libssh.SSH_ERROR:
93
- raise LibsshChannelException(" Failed to poll channel: [%d ]" % rc)
94
92
else :
95
93
rc = libssh.ssh_channel_poll_timeout(self ._libssh_channel, timeout, stderr)
96
- if rc == libssh.SSH_ERROR:
97
- raise LibsshChannelException(" Failed to poll channel: [%d ] " % rc )
94
+ if rc == libssh.SSH_ERROR:
95
+ raise LibsshChannelException(" Failed to poll channel: [{0}] " .format(rc) )
98
96
return rc
99
97
100
98
def read_nonblocking (self , size = 1024 , stderr = 0 ):
@@ -113,7 +111,10 @@ cdef class Channel:
113
111
return self .read_nonblocking(size = size, stderr = stderr)
114
112
115
113
def write (self , data ):
116
- return libssh.ssh_channel_write(self ._libssh_channel, PyBytes_AS_STRING(data), len (data))
114
+ written = libssh.ssh_channel_write(self ._libssh_channel, PyBytes_AS_STRING(data), len (data))
115
+ if written == libssh.SSH_ERROR:
116
+ raise LibsshChannelException(" Failed to write to ssh channel" )
117
+ return written
117
118
118
119
def sendall (self , data ):
119
120
return self .write(data)
@@ -139,23 +140,35 @@ cdef class Channel:
139
140
return response
140
141
141
142
def exec_command (self , command ):
142
- rc = libssh.ssh_channel_request_exec(self ._libssh_channel, command.encode(" utf-8" ))
143
+ # request_exec requires a fresh channel each run, so do not use the existing channel
144
+ cdef libssh.ssh_channel channel = libssh.ssh_channel_new(self ._libssh_session)
145
+ if channel is NULL :
146
+ raise MemoryError
147
+
148
+ rc = libssh.ssh_channel_open_session(channel)
149
+ if rc != libssh.SSH_OK:
150
+ libssh.ssh_channel_free(channel)
151
+ raise LibsshChannelException(" Failed to open_session: [{0}]" .format(rc))
143
152
153
+ rc = libssh.ssh_channel_request_exec(channel, command.encode(" utf-8" ))
144
154
if rc != libssh.SSH_OK:
145
- self .close()
146
- raise CalledProcessError()
155
+ libssh.ssh_channel_close(channel)
156
+ libssh.ssh_channel_free(channel)
157
+ raise LibsshChannelException(" Failed to execute command [{0}]: [{1}]" .format(command, rc))
147
158
result = CompletedProcess(args = command, returncode = - 1 , stdout = b' ' , stderr = b' ' )
148
159
149
160
cdef callbacks.ssh_channel_callbacks_struct cb
150
161
memset(& cb, 0 , sizeof(cb))
151
162
cb.channel_data_function = < callbacks.ssh_channel_data_callback> & _process_outputs
152
163
cb.userdata = < void * > result
153
164
callbacks.ssh_callbacks_init(& cb)
154
- callbacks.ssh_set_channel_callbacks(self ._libssh_channel, & cb)
155
-
156
- libssh.ssh_channel_send_eof(self ._libssh_channel)
165
+ callbacks.ssh_set_channel_callbacks(channel, & cb)
157
166
158
- result.returncode = self .get_channel_exit_status()
167
+ libssh.ssh_channel_send_eof(channel)
168
+ result.returncode = libssh.ssh_channel_get_exit_status(channel)
169
+ if channel is not NULL :
170
+ libssh.ssh_channel_close(channel)
171
+ libssh.ssh_channel_free(channel)
159
172
160
173
return result
161
174
0 commit comments