Mercurial > dropbear
comparison common-channel.c @ 253:84925eceeb13
* rename infd/outfd to writefd/readfd, to avoid confusion
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 20 Oct 2005 16:53:12 +0000 |
parents | 0056419cf0f4 |
children | 82393badfa24 |
comparison
equal
deleted
inserted
replaced
251:b02e8eef3c3a | 253:84925eceeb13 |
---|---|
50 static void removechannel(struct Channel *channel); | 50 static void removechannel(struct Channel *channel); |
51 static void deletechannel(struct Channel *channel); | 51 static void deletechannel(struct Channel *channel); |
52 static void checkinitdone(struct Channel *channel); | 52 static void checkinitdone(struct Channel *channel); |
53 static void checkclose(struct Channel *channel); | 53 static void checkclose(struct Channel *channel); |
54 | 54 |
55 static void closeinfd(struct Channel * channel); | 55 static void closewritefd(struct Channel * channel); |
56 static void closeoutfd(struct Channel * channel, int fd); | 56 static void closereadfd(struct Channel * channel, int fd); |
57 static void closechanfd(struct Channel *channel, int fd, int how); | 57 static void closechanfd(struct Channel *channel, int fd, int how); |
58 | 58 |
59 #define FD_UNINIT (-2) | 59 #define FD_UNINIT (-2) |
60 #define FD_CLOSED (-1) | 60 #define FD_CLOSED (-1) |
61 | 61 |
141 newchan->remotechan = remotechan; | 141 newchan->remotechan = remotechan; |
142 newchan->transwindow = transwindow; | 142 newchan->transwindow = transwindow; |
143 newchan->transmaxpacket = transmaxpacket; | 143 newchan->transmaxpacket = transmaxpacket; |
144 | 144 |
145 newchan->typedata = NULL; | 145 newchan->typedata = NULL; |
146 newchan->infd = FD_UNINIT; | 146 newchan->writefd = FD_UNINIT; |
147 newchan->outfd = FD_UNINIT; | 147 newchan->readfd = FD_UNINIT; |
148 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */ | 148 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */ |
149 newchan->initconn = 0; | 149 newchan->initconn = 0; |
150 newchan->await_open = 0; | 150 newchan->await_open = 0; |
151 | 151 |
152 newchan->writebuf = cbuf_new(RECV_MAXWINDOW); | 152 newchan->writebuf = cbuf_new(RECV_MAXWINDOW); |
175 } | 175 } |
176 return ses.channels[chan]; | 176 return ses.channels[chan]; |
177 } | 177 } |
178 | 178 |
179 /* Iterate through the channels, performing IO if available */ | 179 /* Iterate through the channels, performing IO if available */ |
180 void channelio(fd_set *readfd, fd_set *writefd) { | 180 void channelio(fd_set *readfds, fd_set *writefds) { |
181 | 181 |
182 struct Channel *channel; | 182 struct Channel *channel; |
183 unsigned int i; | 183 unsigned int i; |
184 int ret; | 184 int ret; |
185 | 185 |
190 if (channel == NULL) { | 190 if (channel == NULL) { |
191 /* only process in-use channels */ | 191 /* only process in-use channels */ |
192 continue; | 192 continue; |
193 } | 193 } |
194 | 194 |
195 /* read from program/pipe stdout */ | 195 /* read data and send it over the wire */ |
196 if (channel->outfd >= 0 && FD_ISSET(channel->outfd, readfd)) { | 196 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) { |
197 send_msg_channel_data(channel, 0, 0); | 197 send_msg_channel_data(channel, 0, 0); |
198 } | 198 } |
199 | 199 |
200 /* read from program/pipe stderr */ | 200 /* read stderr data and send it over the wire */ |
201 if (channel->extrabuf == NULL && | 201 if (channel->extrabuf == NULL && |
202 channel->errfd >= 0 && FD_ISSET(channel->errfd, readfd)) { | 202 channel->errfd >= 0 && FD_ISSET(channel->errfd, readfds)) { |
203 send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR); | 203 send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR); |
204 } | 204 } |
205 | 205 |
206 /* if we can read from the infd, it might be closed, so we try to | 206 /* if we can read from the writefd, it might be closed, so we try to |
207 * see if it has errors */ | 207 * see if it has errors */ |
208 if (channel->infd >= 0 && channel->infd != channel->outfd | 208 if (channel->writefd >= 0 && channel->writefd != channel->readfd |
209 && FD_ISSET(channel->infd, readfd)) { | 209 && FD_ISSET(channel->writefd, readfds)) { |
210 if (channel->initconn) { | 210 if (channel->initconn) { |
211 /* Handling for "in progress" connection - this is needed | 211 /* Handling for "in progress" connection - this is needed |
212 * to avoid spinning 100% CPU when we connect to a server | 212 * to avoid spinning 100% CPU when we connect to a server |
213 * which doesn't send anything (tcpfwding) */ | 213 * which doesn't send anything (tcpfwding) */ |
214 checkinitdone(channel); | 214 checkinitdone(channel); |
215 continue; /* Important not to use the channel after | 215 continue; /* Important not to use the channel after |
216 checkinitdone(), as it may be NULL */ | 216 checkinitdone(), as it may be NULL */ |
217 } | 217 } |
218 ret = write(channel->infd, NULL, 0); /* Fake write */ | 218 ret = write(channel->writefd, NULL, 0); /* Fake write */ |
219 if (ret < 0 && errno != EINTR && errno != EAGAIN) { | 219 if (ret < 0 && errno != EINTR && errno != EAGAIN) { |
220 closeinfd(channel); | 220 closewritefd(channel); |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 /* write to program/pipe stdin */ | 224 /* write to program/pipe stdin */ |
225 if (channel->infd >= 0 && FD_ISSET(channel->infd, writefd)) { | 225 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) { |
226 if (channel->initconn) { | 226 if (channel->initconn) { |
227 checkinitdone(channel); | 227 checkinitdone(channel); |
228 continue; /* Important not to use the channel after | 228 continue; /* Important not to use the channel after |
229 checkinitdone(), as it may be NULL */ | 229 checkinitdone(), as it may be NULL */ |
230 } | 230 } |
231 writechannel(channel, channel->infd, channel->writebuf); | 231 writechannel(channel, channel->writefd, channel->writebuf); |
232 } | 232 } |
233 | 233 |
234 /* stderr for client mode */ | 234 /* stderr for client mode */ |
235 if (channel->extrabuf != NULL | 235 if (channel->extrabuf != NULL |
236 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefd)) { | 236 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) { |
237 writechannel(channel, channel->errfd, channel->extrabuf); | 237 writechannel(channel, channel->errfd, channel->extrabuf); |
238 } | 238 } |
239 | 239 |
240 /* now handle any of the channel-closing type stuff */ | 240 /* now handle any of the channel-closing type stuff */ |
241 checkclose(channel); | 241 checkclose(channel); |
242 | 242 |
243 } /* foreach channel */ | 243 } /* foreach channel */ |
244 | 244 |
245 /* Listeners such as TCP, X11, agent-auth */ | 245 /* Listeners such as TCP, X11, agent-auth */ |
246 #ifdef USING_LISTENERS | 246 #ifdef USING_LISTENERS |
247 handle_listeners(readfd); | 247 handle_listeners(readfds); |
248 #endif | 248 #endif |
249 } | 249 } |
250 | 250 |
251 | 251 |
252 /* do all the EOF/close type stuff checking for a channel */ | 252 /* do all the EOF/close type stuff checking for a channel */ |
253 static void checkclose(struct Channel *channel) { | 253 static void checkclose(struct Channel *channel) { |
254 | 254 |
255 TRACE(("checkclose: infd %d, outfd %d, errfd %d, sentclosed %d, recvclosed %d", | 255 TRACE(("checkclose: writefd %d, readfd %d, errfd %d, sentclosed %d, recvclosed %d", |
256 channel->infd, channel->outfd, | 256 channel->writefd, channel->readfd, |
257 channel->errfd, channel->sentclosed, channel->recvclosed)) | 257 channel->errfd, channel->sentclosed, channel->recvclosed)) |
258 TRACE(("writebuf %d extrabuf %s extrabuf %d", | 258 TRACE(("writebuf %d extrabuf %s extrabuf %d", |
259 cbuf_getused(channel->writebuf), | 259 cbuf_getused(channel->writebuf), |
260 channel->writebuf, | 260 channel->writebuf, |
261 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) | 261 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) |
264 | 264 |
265 /* check for exited - currently only used for server sessions, | 265 /* check for exited - currently only used for server sessions, |
266 * if the shell has exited etc */ | 266 * if the shell has exited etc */ |
267 if (channel->type->checkclose) { | 267 if (channel->type->checkclose) { |
268 if (channel->type->checkclose(channel)) { | 268 if (channel->type->checkclose(channel)) { |
269 closeinfd(channel); | 269 closewritefd(channel); |
270 } | 270 } |
271 } | 271 } |
272 | 272 |
273 if (!channel->senteof | 273 if (!channel->senteof |
274 && channel->outfd == FD_CLOSED | 274 && channel->readfd == FD_CLOSED |
275 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { | 275 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { |
276 send_msg_channel_eof(channel); | 276 send_msg_channel_eof(channel); |
277 } | 277 } |
278 | 278 |
279 if (channel->infd == FD_CLOSED | 279 if (channel->writefd == FD_CLOSED |
280 && channel->outfd == FD_CLOSED | 280 && channel->readfd == FD_CLOSED |
281 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { | 281 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { |
282 send_msg_channel_close(channel); | 282 send_msg_channel_close(channel); |
283 } | 283 } |
284 } | 284 } |
285 | 285 |
312 int val; | 312 int val; |
313 socklen_t vallen = sizeof(val); | 313 socklen_t vallen = sizeof(val); |
314 | 314 |
315 TRACE(("enter checkinitdone")) | 315 TRACE(("enter checkinitdone")) |
316 | 316 |
317 if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen) | 317 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen) |
318 || val != 0) { | 318 || val != 0) { |
319 send_msg_channel_open_failure(channel->remotechan, | 319 send_msg_channel_open_failure(channel->remotechan, |
320 SSH_OPEN_CONNECT_FAILED, "", ""); | 320 SSH_OPEN_CONNECT_FAILED, "", ""); |
321 close(channel->infd); | 321 close(channel->writefd); |
322 deletechannel(channel); | 322 deletechannel(channel); |
323 TRACE(("leave checkinitdone: fail")) | 323 TRACE(("leave checkinitdone: fail")) |
324 } else { | 324 } else { |
325 send_msg_channel_open_confirmation(channel, channel->recvwindow, | 325 send_msg_channel_open_confirmation(channel, channel->recvwindow, |
326 channel->recvmaxpacket); | 326 channel->recvmaxpacket); |
327 channel->outfd = channel->infd; | 327 channel->readfd = channel->writefd; |
328 channel->initconn = 0; | 328 channel->initconn = 0; |
329 TRACE(("leave checkinitdone: success")) | 329 TRACE(("leave checkinitdone: success")) |
330 } | 330 } |
331 } | 331 } |
332 | 332 |
384 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); | 384 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); |
385 if (len <= 0) { | 385 if (len <= 0) { |
386 if (len < 0 && errno != EINTR) { | 386 if (len < 0 && errno != EINTR) { |
387 /* no more to write - we close it even if the fd was stderr, since | 387 /* no more to write - we close it even if the fd was stderr, since |
388 * that's a nasty failure too */ | 388 * that's a nasty failure too */ |
389 closeinfd(channel); | 389 closewritefd(channel); |
390 } | 390 } |
391 TRACE(("leave writechannel: len <= 0")) | 391 TRACE(("leave writechannel: len <= 0")) |
392 return; | 392 return; |
393 } | 393 } |
394 | 394 |
395 cbuf_incrread(cbuf, len); | 395 cbuf_incrread(cbuf, len); |
396 channel->recvdonelen += len; | 396 channel->recvdonelen += len; |
397 | 397 |
398 if (fd == channel->infd && len == maxlen && channel->recveof) { | 398 if (fd == channel->writefd && len == maxlen && channel->recveof) { |
399 /* Check if we're closing up */ | 399 /* Check if we're closing up */ |
400 closeinfd(channel); | 400 closewritefd(channel); |
401 TRACE(("leave writechannel: recveof set")) | 401 TRACE(("leave writechannel: recveof set")) |
402 return; | 402 return; |
403 } | 403 } |
404 | 404 |
405 /* Window adjust handling */ | 405 /* Window adjust handling */ |
419 TRACE(("leave writechannel")) | 419 TRACE(("leave writechannel")) |
420 } | 420 } |
421 | 421 |
422 /* Set the file descriptors for the main select in session.c | 422 /* Set the file descriptors for the main select in session.c |
423 * This avoid channels which don't have any window available, are closed, etc*/ | 423 * This avoid channels which don't have any window available, are closed, etc*/ |
424 void setchannelfds(fd_set *readfd, fd_set *writefd) { | 424 void setchannelfds(fd_set *readfds, fd_set *writefds) { |
425 | 425 |
426 unsigned int i; | 426 unsigned int i; |
427 struct Channel * channel; | 427 struct Channel * channel; |
428 | 428 |
429 for (i = 0; i < ses.chansize; i++) { | 429 for (i = 0; i < ses.chansize; i++) { |
434 } | 434 } |
435 | 435 |
436 /* Stuff to put over the wire */ | 436 /* Stuff to put over the wire */ |
437 if (channel->transwindow > 0) { | 437 if (channel->transwindow > 0) { |
438 | 438 |
439 if (channel->outfd >= 0) { | 439 if (channel->readfd >= 0) { |
440 FD_SET(channel->outfd, readfd); | 440 FD_SET(channel->readfd, readfds); |
441 } | 441 } |
442 | 442 |
443 if (channel->extrabuf == NULL && channel->errfd >= 0) { | 443 if (channel->extrabuf == NULL && channel->errfd >= 0) { |
444 FD_SET(channel->errfd, readfd); | 444 FD_SET(channel->errfd, readfds); |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 /* For checking FD status (ie closure etc) - we don't actually | 448 /* For checking FD status (ie closure etc) - we don't actually |
449 * read data from infd */ | 449 * read data from writefd */ |
450 TRACE(("infd = %d, outfd %d, errfd %d, bufused %d", | 450 TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d", |
451 channel->infd, channel->outfd, | 451 channel->writefd, channel->readfd, |
452 channel->errfd, | 452 channel->errfd, |
453 cbuf_getused(channel->writebuf) )) | 453 cbuf_getused(channel->writebuf) )) |
454 if (channel->infd >= 0 && channel->infd != channel->outfd) { | 454 if (channel->writefd >= 0 && channel->writefd != channel->readfd) { |
455 FD_SET(channel->infd, readfd); | 455 FD_SET(channel->writefd, readfds); |
456 } | 456 } |
457 | 457 |
458 /* Stuff from the wire, to local program/shell/user etc */ | 458 /* Stuff from the wire, to local program/shell/user etc */ |
459 if ((channel->infd >= 0 && cbuf_getused(channel->writebuf) > 0 ) | 459 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 ) |
460 || channel->initconn) { | 460 || channel->initconn) { |
461 | 461 |
462 FD_SET(channel->infd, writefd); | 462 FD_SET(channel->writefd, writefds); |
463 } | 463 } |
464 | 464 |
465 if (channel->extrabuf != NULL && channel->errfd >= 0 | 465 if (channel->extrabuf != NULL && channel->errfd >= 0 |
466 && cbuf_getused(channel->extrabuf) > 0 ) { | 466 && cbuf_getused(channel->extrabuf) > 0 ) { |
467 FD_SET(channel->errfd, writefd); | 467 FD_SET(channel->errfd, writefds); |
468 } | 468 } |
469 | 469 |
470 } /* foreach channel */ | 470 } /* foreach channel */ |
471 | 471 |
472 #ifdef USING_LISTENERS | 472 #ifdef USING_LISTENERS |
473 set_listener_fds(readfd); | 473 set_listener_fds(readfds); |
474 #endif | 474 #endif |
475 | 475 |
476 } | 476 } |
477 | 477 |
478 /* handle the channel EOF event, by closing the channel filedescriptor. The | 478 /* handle the channel EOF event, by closing the channel filedescriptor. The |
491 | 491 |
492 channel->recveof = 1; | 492 channel->recveof = 1; |
493 if (cbuf_getused(channel->writebuf) == 0 | 493 if (cbuf_getused(channel->writebuf) == 0 |
494 && (channel->extrabuf == NULL | 494 && (channel->extrabuf == NULL |
495 || cbuf_getused(channel->extrabuf) == 0)) { | 495 || cbuf_getused(channel->extrabuf) == 0)) { |
496 closeinfd(channel); | 496 closewritefd(channel); |
497 } | 497 } |
498 | 498 |
499 TRACE(("leave recv_msg_channel_eof")) | 499 TRACE(("leave recv_msg_channel_eof")) |
500 } | 500 } |
501 | 501 |
539 } | 539 } |
540 | 540 |
541 | 541 |
542 /* close the FDs in case they haven't been done | 542 /* close the FDs in case they haven't been done |
543 * yet (ie they were shutdown etc */ | 543 * yet (ie they were shutdown etc */ |
544 close(channel->infd); | 544 close(channel->writefd); |
545 close(channel->outfd); | 545 close(channel->readfd); |
546 close(channel->errfd); | 546 close(channel->errfd); |
547 | 547 |
548 channel->typedata = NULL; | 548 channel->typedata = NULL; |
549 | 549 |
550 deletechannel(channel); | 550 deletechannel(channel); |
607 dropbear_assert(!channel->sentclosed); | 607 dropbear_assert(!channel->sentclosed); |
608 | 608 |
609 if (isextended) { | 609 if (isextended) { |
610 fd = channel->errfd; | 610 fd = channel->errfd; |
611 } else { | 611 } else { |
612 fd = channel->outfd; | 612 fd = channel->readfd; |
613 } | 613 } |
614 dropbear_assert(fd >= 0); | 614 dropbear_assert(fd >= 0); |
615 | 615 |
616 maxlen = MIN(channel->transwindow, channel->transmaxpacket); | 616 maxlen = MIN(channel->transwindow, channel->transmaxpacket); |
617 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and | 617 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and |
629 TRACE(("buf pos %d data %x", buf->pos, buf->data)) | 629 TRACE(("buf pos %d data %x", buf->pos, buf->data)) |
630 len = read(fd, buf_getwriteptr(buf, maxlen), maxlen); | 630 len = read(fd, buf_getwriteptr(buf, maxlen), maxlen); |
631 if (len <= 0) { | 631 if (len <= 0) { |
632 /* on error/eof, send eof */ | 632 /* on error/eof, send eof */ |
633 if (len == 0 || errno != EINTR) { | 633 if (len == 0 || errno != EINTR) { |
634 closeoutfd(channel, fd); | 634 closereadfd(channel, fd); |
635 } | 635 } |
636 buf_free(buf); | 636 buf_free(buf); |
637 buf = NULL; | 637 buf = NULL; |
638 TRACE(("leave send_msg_channel_data: read err or EOF for fd %d", | 638 TRACE(("leave send_msg_channel_data: read err or EOF for fd %d", |
639 channel->index)); | 639 channel->index)); |
667 channel = getchannel(); | 667 channel = getchannel(); |
668 if (channel == NULL) { | 668 if (channel == NULL) { |
669 dropbear_exit("Unknown channel"); | 669 dropbear_exit("Unknown channel"); |
670 } | 670 } |
671 | 671 |
672 common_recv_msg_channel_data(channel, channel->infd, channel->writebuf); | 672 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf); |
673 } | 673 } |
674 | 674 |
675 /* Shared for data and stderr data - when we receive data, put it in a buffer | 675 /* Shared for data and stderr data - when we receive data, put it in a buffer |
676 * for writing to the local file descriptor */ | 676 * for writing to the local file descriptor */ |
677 void common_recv_msg_channel_data(struct Channel *channel, int fd, | 677 void common_recv_msg_channel_data(struct Channel *channel, int fd, |
687 if (channel->recveof) { | 687 if (channel->recveof) { |
688 dropbear_exit("received data after eof"); | 688 dropbear_exit("received data after eof"); |
689 } | 689 } |
690 | 690 |
691 if (fd < 0) { | 691 if (fd < 0) { |
692 dropbear_exit("received data with bad infd"); | 692 dropbear_exit("received data with bad writefd"); |
693 } | 693 } |
694 | 694 |
695 datalen = buf_getint(ses.payload); | 695 datalen = buf_getint(ses.payload); |
696 | 696 |
697 | 697 |
929 } | 929 } |
930 | 930 |
931 /* set fd non-blocking */ | 931 /* set fd non-blocking */ |
932 setnonblocking(fd); | 932 setnonblocking(fd); |
933 | 933 |
934 chan->infd = chan->outfd = fd; | 934 chan->writefd = chan->readfd = fd; |
935 ses.maxfd = MAX(ses.maxfd, fd); | 935 ses.maxfd = MAX(ses.maxfd, fd); |
936 | 936 |
937 chan->await_open = 1; | 937 chan->await_open = 1; |
938 | 938 |
939 /* now open the channel connection */ | 939 /* now open the channel connection */ |
1006 removechannel(channel); | 1006 removechannel(channel); |
1007 } | 1007 } |
1008 #endif /* USING_LISTENERS */ | 1008 #endif /* USING_LISTENERS */ |
1009 | 1009 |
1010 /* close a stdout/stderr fd */ | 1010 /* close a stdout/stderr fd */ |
1011 static void closeoutfd(struct Channel * channel, int fd) { | 1011 static void closereadfd(struct Channel * channel, int fd) { |
1012 | 1012 |
1013 /* don't close it if it is the same as infd, | 1013 /* don't close it if it is the same as writefd, |
1014 * unless infd is already set -1 */ | 1014 * unless writefd is already set -1 */ |
1015 TRACE(("enter closeoutfd")) | 1015 TRACE(("enter closereadfd")) |
1016 closechanfd(channel, fd, 0); | 1016 closechanfd(channel, fd, 0); |
1017 TRACE(("leave closeoutfd")) | 1017 TRACE(("leave closereadfd")) |
1018 } | 1018 } |
1019 | 1019 |
1020 /* close a stdin fd */ | 1020 /* close a stdin fd */ |
1021 static void closeinfd(struct Channel * channel) { | 1021 static void closewritefd(struct Channel * channel) { |
1022 | 1022 |
1023 TRACE(("enter closeinfd")) | 1023 TRACE(("enter closewritefd")) |
1024 closechanfd(channel, channel->infd, 1); | 1024 closechanfd(channel, channel->writefd, 1); |
1025 TRACE(("leave closeinfd")) | 1025 TRACE(("leave closewritefd")) |
1026 } | 1026 } |
1027 | 1027 |
1028 /* close a fd, how is 0 for stdout/stderr, 1 for stdin */ | 1028 /* close a fd, how is 0 for stdout/stderr, 1 for stdin */ |
1029 static void closechanfd(struct Channel *channel, int fd, int how) { | 1029 static void closechanfd(struct Channel *channel, int fd, int how) { |
1030 | 1030 |
1042 } else { | 1042 } else { |
1043 close(fd); | 1043 close(fd); |
1044 closein = closeout = 1; | 1044 closein = closeout = 1; |
1045 } | 1045 } |
1046 | 1046 |
1047 if (closeout && fd == channel->outfd) { | 1047 if (closeout && fd == channel->readfd) { |
1048 channel->outfd = FD_CLOSED; | 1048 channel->readfd = FD_CLOSED; |
1049 } | 1049 } |
1050 if (closeout && (channel->extrabuf == NULL) && (fd == channel->errfd)) { | 1050 if (closeout && (channel->extrabuf == NULL) && (fd == channel->errfd)) { |
1051 channel->errfd = FD_CLOSED; | 1051 channel->errfd = FD_CLOSED; |
1052 } | 1052 } |
1053 | 1053 |
1054 if (closein && fd == channel->infd) { | 1054 if (closein && fd == channel->writefd) { |
1055 channel->infd = FD_CLOSED; | 1055 channel->writefd = FD_CLOSED; |
1056 } | 1056 } |
1057 if (closein && (channel->extrabuf != NULL) && (fd == channel->errfd)) { | 1057 if (closein && (channel->extrabuf != NULL) && (fd == channel->errfd)) { |
1058 channel->errfd = FD_CLOSED; | 1058 channel->errfd = FD_CLOSED; |
1059 } | 1059 } |
1060 | 1060 |
1061 /* if we called shutdown on it and all references are gone, then we | 1061 /* if we called shutdown on it and all references are gone, then we |
1062 * need to close() it to stop it lingering */ | 1062 * need to close() it to stop it lingering */ |
1063 if (channel->type->sepfds && channel->outfd == FD_CLOSED | 1063 if (channel->type->sepfds && channel->readfd == FD_CLOSED |
1064 && channel->infd == FD_CLOSED && channel->errfd == FD_CLOSED) { | 1064 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) { |
1065 close(fd); | 1065 close(fd); |
1066 } | 1066 } |
1067 } | 1067 } |