/** * @brief Write into a remote scp file. * * @param[in] scp The scp handle. * * @param[in] buffer The buffer to write. * * @param[in] len The number of bytes to write. * * @returns SSH_OK if the write was successful, SSH_ERROR an error * occured while writing. */ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){ int w; int r; uint8_t code; if(scp==NULL) return SSH_ERROR; if(scp->state != SSH_SCP_WRITE_WRITING){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_write called under invalid state"); return SSH_ERROR; } if(scp->processed + len > scp->filelen) len = (size_t) (scp->filelen - scp->processed); /* hack to avoid waiting for window change */ r = ssh_channel_poll(scp->channel, 0); if (r == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } w=ssh_channel_write(scp->channel,buffer,len); if(w != SSH_ERROR) scp->processed += w; else { scp->state=SSH_SCP_ERROR; //return=channel_get_exit_status(scp->channel); return SSH_ERROR; } /* Far end sometimes send a status message, which we need to read * and handle */ r = ssh_channel_poll(scp->channel,0); if(r > 0){ r = ssh_channel_read(scp->channel, &code, 1, 0); if(r == SSH_ERROR){ return SSH_ERROR; } if(code == 1 || code == 2){ ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Error: status code %i received", code); return SSH_ERROR; } } /* Check if we arrived at end of file */ if(scp->processed == scp->filelen) { code = 0; w = ssh_channel_write(scp->channel, &code, 1); if(w == SSH_ERROR){ scp->state = SSH_SCP_ERROR; return SSH_ERROR; } scp->processed=scp->filelen=0; scp->state=SSH_SCP_WRITE_INITED; } return SSH_OK; }
int SSH_Socket::pollSocket() { int numready; if(sshChannel && ssh_channel_is_open(sshChannel) && ssh_channel_poll(sshChannel,0) > 0) { numready = 1; } else { numready = 0; } if(ssh_channel_poll(sshChannel,0) < 0) TheSocketHandler::Instance()->setActive(false); return numready; }
static size_t read_from_channel_port (SCM channel, SCM dst, size_t start, size_t count) #define FUNC_NAME "read_from_channel_port" { char *data = (char *) SCM_BYTEVECTOR_CONTENTS (dst) + start; struct channel_data *cd = _scm_to_channel_data (channel); int res; if (! ssh_channel_is_open (cd->ssh_channel)) return 0; /* Update state of the underlying channel and check whether we have data to read or not. */ res = ssh_channel_poll (cd->ssh_channel, cd->is_stderr); if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "Error polling channel", channel); else if (res == SSH_EOF) return 0; /* Note: `ssh_channel_read' sometimes returns 0 even if `ssh_channel_poll' returns a positive value. */ res = ssh_channel_read (cd->ssh_channel, data, count, cd->is_stderr); if (res == SSH_AGAIN) res = 0; else if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "Error reading from the channel", channel); assert (res >= 0); return res; }
/* Poll the underlying SSH channel for data, return amount of data available for reading. Throw `guile-ssh-error' on error. */ static int ptob_input_waiting (SCM channel) #define FUNC_NAME "ptob_input_waiting" { struct channel_data *cd = _scm_to_channel_data (channel); int res = ssh_channel_poll (cd->ssh_channel, cd->is_stderr); if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "An error occured.", channel); return (res != SSH_EOF) ? res : 0; }
/** * @brief Write into a remote scp file. * * @param[in] scp The scp handle. * * @param[in] buffer The buffer to write. * * @param[in] len The number of bytes to write. * * @returns SSH_OK if the write was successful, SSH_ERROR an error * occured while writing. */ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){ int w; //int r; //uint8_t code; if(scp==NULL) return SSH_ERROR; if(scp->state != SSH_SCP_WRITE_WRITING){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_write called under invalid state"); return SSH_ERROR; } if(scp->processed + len > scp->filelen) len = scp->filelen - scp->processed; /* hack to avoid waiting for window change */ ssh_channel_poll(scp->channel,0); w=ssh_channel_write(scp->channel,buffer,len); if(w != SSH_ERROR) scp->processed += w; else { scp->state=SSH_SCP_ERROR; //return=channel_get_exit_status(scp->channel); return SSH_ERROR; } /* Check if we arrived at end of file */ if(scp->processed == scp->filelen) { /* r=channel_read(scp->channel,&code,1,0); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } if(code != 0){ ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code); scp->state=SSH_SCP_ERROR; return SSH_ERROR; } */ scp->processed=scp->filelen=0; scp->state=SSH_SCP_WRITE_INITED; } return SSH_OK; }
/* Read data from the channel. Return EOF if no data is available or throw `guile-ssh-error' if an error occured. */ static int ptob_fill_input (SCM channel) #define FUNC_NAME "ptob_fill_input" { struct channel_data *cd = _scm_to_channel_data (channel); scm_port *pt = SCM_PTAB_ENTRY (channel); int res; if (! ssh_channel_is_open (cd->ssh_channel)) return EOF; /* Update state of the underlying channel and check whether we have data to read or not. */ res = ssh_channel_poll (cd->ssh_channel, cd->is_stderr); if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "Error polling channel", channel); else if (res == SSH_EOF) return EOF; res = ssh_channel_read (cd->ssh_channel, pt->read_buf, pt->read_buf_size, cd->is_stderr); if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "Error reading from the channel", channel); /* `ssh_channel_read' sometimes returns 0 even if `ssh_channel_poll' returns a positive value. So we must ensure that res != 0 otherwise an assertion in `scm_i_fill_input' won't be meet (see `ports.c' in Guile 2.0.9). */ if ((! res) || (res == SSH_AGAIN)) return EOF; pt->read_pos = pt->read_buf; pt->read_end = pt->read_buf + res; return *pt->read_buf; }
static void select_loop(ssh_session_t *session,ssh_channel_t *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_t *channels[2], *outchannels[2]; int lus; int eof=0; int maxfd; unsigned int r; 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(signal_delayed) { sizechanged(); } if(ret == EINTR) { continue; } if(FD_ISSET(0, &fds)) { lus = read(0, buffer, sizeof(buffer)); if(lus) ssh_channel_write(channel, buffer, lus); else { eof = 1; ssh_channel_send_eof(channel); } } if(channel && ssh_channel_is_closed(channel)) { ssh_channel_free(channel); channel=NULL; channels[0]=NULL; } if(outchannels[0]) { while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,0))!=0) { lus = ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),0); if(lus == -1) { fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus == 0) { ssh_channel_free(channel); channel=channels[0]=NULL; } else { if (write(1,buffer,lus) < 0) { fprintf(stderr, "Error writing to buffer\n"); return; } } } while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,1))!=0) /* stderr */ { lus = ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),1); if(lus == -1) { fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus == 0) { ssh_channel_free(channel); channel = channels[0] = NULL; } else { if (write(2, buffer, lus) < 0) { fprintf(stderr, "Error writing to buffer\n"); return; } } } } if(channel && ssh_channel_is_closed(channel)) { ssh_channel_free(channel); channel=NULL; } } while (ret == EINTR || ret == SSH_EINTR); } }
/** * @brief A wrapper for the select syscall * * This functions acts more or less like the select(2) syscall.\n * There is no support for writing or exceptions.\n * * @param[in] channels Arrays of channels pointers terminated by a NULL. * It is never rewritten. * * @param[out] outchannels Arrays of same size that "channels", there is no need * to initialize it. * * @param[in] maxfd Maximum +1 file descriptor from readfds. * * @param[in] readfds A fd_set of file descriptors to be select'ed for * reading. * * @param[in] timeout A timeout for the select. * * @return SSH_OK on success, * SSH_ERROR on error, * SSH_EINTR if it was interrupted. In that case, * just restart it. * * @warning libssh is not reentrant here. That means that if a signal is caught * during the processing of this function, you cannot call libssh * functions on sessions that are busy with ssh_select(). * * @see select(2) */ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd, fd_set *readfds, struct timeval *timeout) { fd_set origfds; socket_t fd; int i,j; int rc; int base_tm, tm; struct ssh_timestamp ts; ssh_event event = ssh_event_new(); int firstround=1; base_tm = tm=timeout->tv_sec * 1000 + timeout->tv_usec/1000; for (i=0 ; channels[i] != NULL; ++i){ ssh_event_add_session(event, channels[i]->session); } FD_ZERO(&origfds); for (fd = 0; fd < maxfd ; fd++) { if (FD_ISSET(fd, readfds)) { ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds); FD_SET(fd, &origfds); } } outchannels[0] = NULL; FD_ZERO(readfds); ssh_timestamp_init(&ts); do { /* Poll every channel */ j = 0; for (i = 0; channels[i]; i++) { if(ssh_channel_poll(channels[i], 0) != 0) { outchannels[j] = channels[i]; j++; } else if(ssh_channel_poll(channels[i], 1) != 0) { outchannels[j] = channels[i]; j++; } } outchannels[j] = NULL; if(j != 0) break; /* watch if a user socket was triggered */ for (fd = 0; fd < maxfd; fd++) { if (FD_ISSET(fd, readfds)) { goto out; } } /* If the timeout is elapsed, we should go out */ if(!firstround && ssh_timeout_elapsed(&ts, base_tm)) goto out; /* since there's nothing, let's fire the polling */ rc = ssh_event_dopoll(event,tm); if (rc == SSH_ERROR){ goto out; } tm = ssh_timeout_update(&ts, base_tm); firstround=0; } while (1); out: for (fd = 0; fd < maxfd; fd++) { if (FD_ISSET(fd, &origfds)) { ssh_event_remove_fd(event, fd); } } ssh_event_free(event); return SSH_OK; }
/* channel_select base main loop, with a standard select(2) */ static void select_loop(ssh_session session,ssh_channel channel){ fd_set fds; struct timeval timeout; char buffer[4096]; ssh_buffer readbuf=ssh_buffer_new(); ssh_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,sizeof(buffer)); if(lus) ssh_channel_write(channel,buffer,lus); else { eof=1; ssh_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=ssh_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 && ssh_channel_is_closed(channel)){ ssh_channel_free(channel); channel=NULL; channels[0]=NULL; } if(channels[0]){ while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){ lus=channel_read_buffer(channel,readbuf,0,0); if(lus==-1){ fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus==0){ ssh_channel_free(channel); channel=channels[0]=NULL; } else if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) { fprintf(stderr, "Error writing to buffer\n"); return; } } while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */ lus=channel_read_buffer(channel,readbuf,0,1); if(lus==-1){ fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus==0){ ssh_channel_free(channel); channel=channels[0]=NULL; } else if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) { fprintf(stderr, "Error writing to buffer\n"); return; } } } if(channel && ssh_channel_is_closed(channel)){ ssh_channel_free(channel); channel=NULL; } } ssh_buffer_free(readbuf); }
int channel_poll(ssh_channel channel, int is_stderr){ return ssh_channel_poll(channel, is_stderr); }