+int
+chan_is_dead(Channel *c, int do_send)
+{
+ if (c->type == SSH_CHANNEL_ZOMBIE) {
+ debug2("channel %d: zombie", c->self);
+ return 1;
+ }
+ if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
+ return 0;
+ if (!compat20) {
+ debug2("channel %d: is dead", c->self);
+ return 1;
+ }
+ if ((datafellows & SSH_BUG_EXTEOF) &&
+ c->extended_usage == CHAN_EXTENDED_WRITE &&
+ c->efd != -1 &&
+ buffer_len(&c->extended) > 0) {
+ debug2("channel %d: active efd: %d len %d",
+ c->self, c->efd, buffer_len(&c->extended));
+ return 0;
+ }
+ if (c->flags & CHAN_LOCAL) {
+ debug2("channel %d: is dead (local)", c->self);
+ return 1;
+ }
+ if (!(c->flags & CHAN_CLOSE_SENT)) {
+ if (do_send) {
+ chan_send_close2(c);
+ } else {
+ /* channel would be dead if we sent a close */
+ if (c->flags & CHAN_CLOSE_RCVD) {
+ debug2("channel %d: almost dead",
+ c->self);
+ return 1;
+ }
+ }
+ }
+ if ((c->flags & CHAN_CLOSE_SENT) &&
+ (c->flags & CHAN_CLOSE_RCVD)) {
+ debug2("channel %d: is dead", c->self);
+ return 1;