int ssh_scp_close(ssh_scp scp){ char buffer[128]; int err; if(scp->channel != NULL){ if(channel_send_eof(scp->channel) == SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } /* avoid situations where data are buffered and * not yet stored on disk. This can happen if the close is sent * before we got the EOF back */ while(!channel_is_eof(scp->channel)){ err=channel_read(scp->channel,buffer,sizeof(buffer),0); if(err==SSH_ERROR) break; } if(channel_close(scp->channel) == SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } channel_free(scp->channel); scp->channel=NULL; } scp->state=SSH_SCP_NEW; return SSH_OK; }
/** * @brief Close a channel. * * This sends an end of file and then closes the channel. You won't be able * to recover any data the server was going to send or was in buffers. * * @param channel The channel to close. * * @return SSH_SUCCESS on success\n * SSH_ERROR on error * * @see channel_free() * @see channel_eof() */ int channel_close(CHANNEL *channel){ SSH_SESSION *session = channel->session; int rc = 0; enter_function(); if (channel->local_eof == 0) { rc = channel_send_eof(channel); } if (rc != SSH_OK) { leave_function(); return rc; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_CLOSE) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0) { goto error; } rc = packet_send(session); ssh_log(session, SSH_LOG_PACKET, "Sent a close on client channel (%d:%d)", channel->local_channel, channel->remote_channel); if(rc == SSH_OK) { channel->open = 0; } leave_function(); return rc; error: buffer_free(session->out_buffer); leave_function(); return rc; }
static void select_loop(ssh_session session,ssh_channel channel){ fd_set fds; struct timeval timeout; char buffer[4096]; /* channels will be set to the channels to poll. * outchannels will contain the result of the poll */ ssh_channel channels[2], outchannels[2]; int lus; int eof=0; int maxfd; int ret; while(channel){ do{ FD_ZERO(&fds); if(!eof) FD_SET(0,&fds); timeout.tv_sec=30; timeout.tv_usec=0; FD_SET(ssh_get_fd(session),&fds); maxfd=ssh_get_fd(session)+1; channels[0]=channel; // set the first channel we want to read from channels[1]=NULL; ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout); if(ret==EINTR) continue; if(FD_ISSET(0,&fds)){ lus=read(0,buffer,sizeof(buffer)); if(lus) channel_write(channel,buffer,lus); else { eof=1; channel_send_eof(channel); } } if(channel && channel_is_closed(channel)){ channel_free(channel); channel=NULL; channels[0]=NULL; } if(outchannels[0]){ while(channel && channel_is_open(channel) && channel_poll(channel,0)){ lus=channel_read(channel,buffer,sizeof(buffer),0); if(lus==-1){ fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus==0){ channel_free(channel); channel=channels[0]=NULL; } else { ret = write(1, buffer, lus); if (ret < 0) { fprintf(stderr, "Error writing to stdin: %s", strerror(errno)); return; } } } while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */ lus=channel_read(channel,buffer,sizeof(buffer),1); if(lus==-1){ fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus==0){ channel_free(channel); channel=channels[0]=NULL; } else { ret = write(2, buffer, lus); if (ret < 0) { fprintf(stderr, "Error writing to stderr: %s", strerror(errno)); return; } } } } if(channel && channel_is_closed(channel)){ channel_free(channel); channel=NULL; } } while (ret==EINTR || ret==SSH_EINTR); } }
void select_loop(SSH_SESSION *session,CHANNEL *channel){ fd_set fds; struct timeval timeout; char buffer[10]; BUFFER *readbuf=buffer_new(); CHANNEL *channels[2]; int lus; int eof=0; int maxfd; int ret; while(channel){ /* when a signal is caught, ssh_select will return * with SSH_EINTR, which means it should be started * again. It lets you handle the signal the faster you * can, like in this window changed example. Of course, if * your signal handler doesn't call libssh at all, you're * free to handle signals directly in sighandler. */ do{ FD_ZERO(&fds); if(!eof) FD_SET(0,&fds); timeout.tv_sec=30; timeout.tv_usec=0; FD_SET(ssh_get_fd(session),&fds); maxfd=ssh_get_fd(session)+1; ret=select(maxfd,&fds,NULL,NULL,&timeout); if(ret==EINTR) continue; if(FD_ISSET(0,&fds)){ lus=read(0,buffer,10); if(lus) channel_write(channel,buffer,lus); else { eof=1; channel_send_eof(channel); } } if(FD_ISSET(ssh_get_fd(session),&fds)){ ssh_set_fd_toread(session); } channels[0]=channel; // set the first channel we want to read from channels[1]=NULL; ret=channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll if(signal_delayed) sizechanged(); } while (ret==EINTR || ret==SSH_EINTR); // we already looked for input from stdin. Now, we are looking for input from the channel if(channel && channel_is_closed(channel)){ channel_free(channel); channel=NULL; channels[0]=NULL; } if(channels[0]){ while(channel && channel_is_open(channel) && channel_poll(channel,0)){ lus=channel_read(channel,readbuf,0,0); if(lus==-1){ ssh_say(0,"error reading channel : %s\n",ssh_get_error(session)); return; } if(lus==0){ ssh_say(1,"EOF received\n"); channel_free(channel); channel=channels[0]=NULL; } else write(1,buffer_get(readbuf),lus); } while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */ lus=channel_read(channel,readbuf,0,1); if(lus==-1){ ssh_say(0,"error reading channel : %s\n",ssh_get_error(session)); return; } if(lus==0){ ssh_say(1,"EOF received\n"); channel_free(channel); channel=channels[0]=NULL; } else write(2,buffer_get(readbuf),lus); } } if(channel && channel_is_closed(channel)){ channel_free(channel); channel=NULL; } } buffer_free(readbuf); }
/** * Launch a command over SSH * @param QString command The command to launch * @return bool true if it's ok, false else */ bool Kssh::launch(QString command) { this->init(); this->m_command = command; int result; ssh_channel channel = channel_new(this->m_session); if (channel == NULL) { Klog::error(QString("Impossible to open a new channel") + QString(ssh_get_error(this->m_session))); ssh_disconnect(this->m_session); ssh_finalize(); return false; } if (channel_open_session(channel) == SSH_ERROR) { Klog::error(QString("Impossible to open a session in the channel") + QString(ssh_get_error(this->m_session))); channel_close(channel); ssh_disconnect(this->m_session); ssh_finalize(); return false; } result = channel_request_exec(channel, this->m_command.toStdString().c_str()); if (result == SSH_ERROR) { Klog::error(QString("Impossible to launch command : ") + QString(ssh_get_error(this->m_session))); channel_close(channel); ssh_disconnect(this->m_session); ssh_finalize(); return false; } else { #ifdef DEBUG Klog::debug(QString("Execution de la commande : ") + this->m_command); #endif // read the buffer char *buf = NULL; buf = new char[512]; int rc = 0; do { if (channel_is_open(channel)) { rc = channel_read(channel, buf, sizeof(buf), 0); if (rc > 0) { this->m_return += QString::fromLatin1(buf, rc); } } } while (rc > 0); delete[] buf; channel_send_eof(channel); channel_close(channel); ssh_disconnect(this->m_session); ssh_finalize(); } return true; }