int main(void) { if ((chan = make_channel()) == NULL) { perror("make_channel() error"); exit(EXIT_FAILURE); } size_t i; for (i = 0; i < THREADS_N; i++) { int thr_res = pthread_create(&threads[i], NULL, thr_fn, (void *) (uintptr_t) i); if (thr_res != 0) { fprintf(stderr, "pthread_create(3) error: %s\n", strerror(thr_res)); exit(EXIT_FAILURE); } } for (i = 0; i < COUNT; i++) { int j; if (channel_read(chan, (char *) &j, sizeof(j)) == -1) { perror("channel_read() error"); exit(EXIT_FAILURE); } printf("%d\n", j); } return 0; }
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 initializes the sending of a file to a scp in sink mode * @param scp the scp handle. * @param filename Name of the file being sent. It should not contain any path indicator * @param size Exact size in bytes of the file being sent. * @param mode Unix permissions for the new file, e.g. 0644 * @returns SSH_OK if the file is ready to be sent. * @returns SSH_ERROR if an error happened. */ int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){ char buffer[1024]; int r; uint8_t code; char *file; char *perms; if(scp->state != SSH_SCP_WRITE_INITED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_file called under invalid state"); return SSH_ERROR; } file=ssh_basename(filename); perms=ssh_scp_string_mode(mode); ssh_log(scp->session,SSH_LOG_PROTOCOL,"SCP pushing file %s, size %" PRIdS " with permissions '%s'",file,size,perms); snprintf(buffer, sizeof(buffer), "C%s %" PRIdS " %s\n", perms, size, file); SAFE_FREE(file); SAFE_FREE(perms); r=channel_write(scp->channel,buffer,strlen(buffer)); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=channel_read(scp->channel,&code,1,0); 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->filelen = size; scp->processed = 0; scp->state=SSH_SCP_WRITE_WRITING; return SSH_OK; }
/** @brief waits for a response of the scp server * @internal * @param response pointer where the response message must be * copied if any. This pointer must then be free'd. * @returns the return code. * @returns SSH_ERROR a error occured */ int ssh_scp_response(ssh_scp scp, char **response){ unsigned char code; int r; char msg[128]; r=channel_read(scp->channel,&code,1,0); if(r == SSH_ERROR) return SSH_ERROR; if(code == 0) return 0; if(code > 2){ ssh_set_error(scp->session,SSH_FATAL, "SCP: invalid status code %ud received", code); scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=ssh_scp_read_string(scp,msg,sizeof(msg)); if(r==SSH_ERROR) return r; /* Warning */ if(code == 1){ ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Warning: status code 1 received: %s", msg); ssh_log(scp->session,SSH_LOG_RARE,"SCP: Warning: status code 1 received: %s", msg); if(response) *response=strdup(msg); return 1; } if(code == 2){ ssh_set_error(scp->session,SSH_FATAL, "SCP: Error: status code 2 received: %s", msg); if(response) *response=strdup(msg); return 2; } /* Not reached */ return SSH_ERROR; }
/** @brief creates a directory in a scp in sink mode * @param scp the scp handle. * @param dirname Name of the directory being created. * @param mode Unix permissions for the new directory, e.g. 0755. * @returns SSH_OK if the directory was created. * @returns SSH_ERROR if an error happened. * @see ssh_scp_leave_directory */ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){ char buffer[1024]; int r; uint8_t code; char *dir; char *perms; if(scp->state != SSH_SCP_WRITE_INITED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_directory called under invalid state"); return SSH_ERROR; } dir=ssh_basename(dirname); perms=ssh_scp_string_mode(mode); snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, dir); SAFE_FREE(dir); SAFE_FREE(perms); r=channel_write(scp->channel,buffer,strlen(buffer)); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=channel_read(scp->channel,&code,1,0); 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; } return SSH_OK; }
int terminal_read(uchar_t *buf, size_t size) { #ifdef ENABLE_SSH return channel_read(ssh_chan, buf, size, 0); #else // ENABLE_SSH return file_read(STDIN_FILENO, buf, size); #endif // ENABLE_SSH }
static void channel_read_netbeans(int id) { channel_T *channel = channel_from_id(id); if (channel == NULL) ch_errorn(NULL, "Channel %d not found", id); else channel_read(channel, -1, "messageFromNetbeans"); }
int SSHClient::sshRead(std::uint8_t *buf, size_t size) { GNASH_REPORT_FUNCTION; int ret = channel_read(_channel, buf, size, 0); if (ret < 0) { log_error(_("SSH read error was: \"%s\"!"), ssh_get_error(_session)); } return ret; }
int sdb_channel_read(sdb_channel_t *chan, void *data) { int status; if ((! chan) || (! data)) return -1; pthread_mutex_lock(&chan->lock); status = channel_read(chan, data); pthread_mutex_unlock(&chan->lock); return status; } /* sdb_channel_read */
int SSHClient::readChannel(ssh_channel channel, cygnal::Buffer &buf) { // GNASH_REPORT_FUNCTION; int ret = -1; if (channel) { ret = channel_read(channel, buf.reference(), buf.size(), 0); } else { log_error(_("Can't read from a non-existent channel!")); } return ret; }
int ssh_scp_init(ssh_scp scp){ int r; char execbuffer[1024]; uint8_t code; if(scp->state != SSH_SCP_NEW){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_init called under invalid state"); return SSH_ERROR; } ssh_log(scp->session,SSH_LOG_PROTOCOL,"Initializing scp session %s %son location '%s'", scp->mode==SSH_SCP_WRITE?"write":"read", scp->recursive?"recursive ":"", scp->location); scp->channel=channel_new(scp->session); if(scp->channel == NULL){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r= channel_open_session(scp->channel); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } if(scp->mode == SSH_SCP_WRITE) snprintf(execbuffer,sizeof(execbuffer),"scp -t %s %s", scp->recursive ? "-r":"", scp->location); else snprintf(execbuffer,sizeof(execbuffer),"scp -f %s %s", scp->recursive ? "-r":"", scp->location); if(channel_request_exec(scp->channel,execbuffer) == SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } if(scp->mode == SSH_SCP_WRITE){ r=channel_read(scp->channel,&code,1,0); 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; } } else { channel_write(scp->channel,"",1); } if(scp->mode == SSH_SCP_WRITE) scp->state=SSH_SCP_WRITE_INITED; else scp->state=SSH_SCP_READ_INITED; return SSH_OK; }
/* * The type of "rfds" is hidden to avoid problems with the function proto. */ int channel_select_check(int ret_in, void *rfds_in) { int ret = ret_in; int i; fd_set *rfds = rfds_in; for (i = 0; i < channel_count; ++i) if (ret > 0 && channels[i].ch_fd >= 0 && FD_ISSET(channels[i].ch_fd, rfds)) { channel_read(i); --ret; } return ret; }
/* * The type of "fds" is hidden to avoid problems with the function proto. */ int channel_poll_check(int ret_in, void *fds_in) { int ret = ret_in; int i; struct pollfd *fds = fds_in; for (i = 0; i < channel_count; ++i) if (ret > 0 && channels[i].ch_idx != -1 && fds[channels[i].ch_idx].revents & POLLIN) { channel_read(i); --ret; } return ret; }
/** * @brief reads a string on a channel, terminated by '\n' * @param scp the scp handle. * @param buffer pointer to a buffer to place the string * @param len size of the buffer in bytes. If the string is bigger * than len-1, only len-1 bytes are read and the string * is null-terminated. * @returns SSH_OK The string was read * @returns SSH_ERROR Error happened while reading */ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){ size_t r=0; int err=SSH_OK; while(r<len-1){ err=channel_read(scp->channel,&buffer[r],1,0); if(err==SSH_ERROR){ break; } if(err==0){ ssh_set_error(scp->session,SSH_FATAL,"End of file while reading string"); err=SSH_ERROR; break; } r++; if(buffer[r-1] == '\n') break; } buffer[r]=0; return err; }
/** @brief Read from a remote scp file * @param scp the scp handle. * @param buffer Destination buffer * @param size Size of the buffer * @returns Number of bytes read * @returns SSH_ERROR An error happened while reading */ int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){ int r; int code; if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){ r=ssh_scp_accept_request(scp); if(r==SSH_ERROR) return r; } if(scp->state != SSH_SCP_READ_READING){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_read called under invalid state"); return SSH_ERROR; } if(scp->processed + size > scp->filelen) size = scp->filelen - scp->processed; if(size > 65536) size=65536; /* avoid too large reads */ r=channel_read(scp->channel,buffer,size,0); if(r != SSH_ERROR) scp->processed += r; else { scp->state=SSH_SCP_ERROR; return SSH_ERROR; } /* Check if we arrived at end of file */ if(scp->processed == scp->filelen) { scp->processed=scp->filelen=0; channel_write(scp->channel,"",1); code=ssh_scp_response(scp,NULL); if(code == 0){ scp->state=SSH_SCP_READ_INITED; return r; } if(code==1){ scp->state=SSH_SCP_READ_INITED; return SSH_ERROR; } scp->state=SSH_SCP_ERROR; return SSH_ERROR; } return r; }
/** * @brief Leaves a directory * @returns SSH_OK if the directory was created. * @returns SSH_ERROR if an error happened. * @see ssh_scp_push_directory */ int ssh_scp_leave_directory(ssh_scp scp){ char buffer[]="E\n"; int r; uint8_t code; if(scp->state != SSH_SCP_WRITE_INITED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_leave_directory called under invalid state"); return SSH_ERROR; } r=channel_write(scp->channel,buffer,strlen(buffer)); if(r==SSH_ERROR){ scp->state=SSH_SCP_ERROR; return SSH_ERROR; } r=channel_read(scp->channel,&code,1,0); 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; } return SSH_OK; }
static void create_files(ssh_session session){ ssh_channel channel=channel_new(session); char buffer[1]; if(channel == NULL){ fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session)); exit(EXIT_FAILURE); } if(channel_open_session(channel) != SSH_OK){ fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session)); exit(EXIT_FAILURE); } if(channel_request_exec(channel,createcommand) != SSH_OK){ fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session)); exit(EXIT_FAILURE); } while(!channel_is_eof(channel)){ channel_read(channel,buffer,1,1); write(1,buffer,1); } channel_close(channel); channel_free(channel); }
/** * @brief Do a nonblocking read on the channel. * * A nonblocking read on the specified channel. it will return <= count bytes of * data read atomicly. * * @param channel The channel to read from. * * @param dest A pointer to a destination buffer. * * @param count The count of bytes of data to be read. * * @param is_stderr A boolean to select the stderr stream. * * @return The number of bytes read, 0 if nothing is available or * SSH_ERROR on error. * * @warning Don't forget to check for EOF as it would return 0 here. * * @see channel_is_eof() */ int channel_read_nonblocking(CHANNEL *channel, void *dest, u32 count, int is_stderr) { SSH_SESSION *session = channel->session; u32 to_read; int rc; enter_function(); to_read = channel_poll(channel, is_stderr); if (to_read <= 0) { leave_function(); return to_read; /* may be an error code */ } if (to_read > count) { to_read = count; } rc = channel_read(channel, dest, to_read, is_stderr); leave_function(); return rc; }
int sdb_channel_select(sdb_channel_t *chan, int *wantread, void *read_data, int *wantwrite, void *write_data, const struct timespec *timeout) { int status = 0; if (! chan) { errno = EINVAL; return -1; } if ((! wantread) && (! read_data) && (! wantwrite) && (! write_data)) { errno = EINVAL; return -1; } pthread_mutex_lock(&chan->lock); while (! status) { int read_status, write_status; read_status = channel_read(chan, read_data); write_status = channel_write(chan, write_data); if ((! read_status) || (! write_status)) { if (wantread) *wantread = read_status == 0; if (wantwrite) *wantwrite = write_status == 0; if (((wantread || read_data) && (! read_status)) || ((wantwrite || write_data) && (! write_status))) break; } if (chan->shutdown) { if (read_status) status = EBADF; break; } if (timeout) { struct timespec abstime; if (clock_gettime(CLOCK_REALTIME, &abstime)) { pthread_mutex_unlock(&chan->lock); return -1; } abstime.tv_sec += timeout->tv_sec; abstime.tv_nsec += timeout->tv_nsec; if (abstime.tv_nsec > 1000000000) { abstime.tv_nsec -= 1000000000; abstime.tv_sec += 1; } status = pthread_cond_timedwait(&chan->cond, &chan->lock, &abstime); } else status = pthread_cond_wait(&chan->cond, &chan->lock); } pthread_mutex_unlock(&chan->lock); if (status) { errno = status; return -1; } return 0; } /* sdb_channel_select */
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); } }
/** * 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; }
/* * File download open completion handler for when a channel for a given file has * been opened and is ready to be read from. */ DWORD file_download_open_complete(Remote *remote, Channel *channel, LPVOID context, DWORD result) { ChannelCompletionRoutine complete; FileDownloadContext *ctx = (FileDownloadContext *)context; DWORD res = ERROR_SUCCESS; BOOL textPrinted = TRUE; do { // If the result was not successful, no sense in continuing if ((!channel) || (result != ERROR_SUCCESS)) { console_write_output( "\n" INBOUND_PREFIX " FS: file_download_open failed, result %lu.\n", result); res = result; break; } // Try to open the local target file for writing if (!(ctx->fd = fopen(ctx->target, "wb"))) { console_write_output( "\n" "Error: Local file '%s' could not be opened for writing.\n", ctx->target); res = ERROR_FILE_NOT_FOUND; break; } textPrinted = FALSE; // Initialize the completion context for reading memset(&complete, 0, sizeof(complete)); complete.context = ctx; complete.routine.read = file_download_read_complete; // Read from the remote file res = channel_read(channel, remote, NULL, 0, 8192, &complete); } while (0); // If the result was not successful, clean up the context here if (res != ERROR_SUCCESS) { // Close the channel if it's valid if (channel) channel_close(channel, remote, NULL, 0, NULL); // Free the context on error if (ctx->fd) fclose(ctx->fd); free(ctx); } if (textPrinted) console_write_prompt(); return res; }
/* * Download completion routine for a read request. */ DWORD file_download_read_complete(Remote *remote, Channel *channel, LPVOID context, DWORD result, PUCHAR buffer, ULONG bytesRead) { ChannelCompletionRoutine complete; FileDownloadContext *ctx = (FileDownloadContext *)context; DWORD bytesWritten; BOOL textPrinted = TRUE; DWORD res = ERROR_SUCCESS; BOOL cleanup = FALSE; do { // If the result was not successful, no sense in continuing if ((!channel) || (result != ERROR_SUCCESS)) { console_write_output( "\n" INBOUND_PREFIX " FS: file_download_read failed, result %lu.\n", result); res = result; break; } // Were no bytes read from the remote endpoint? if (!bytesRead) { console_write_output( "\n" INBOUND_PREFIX " FS: Download to '%s' completed.\n", ctx->target); cleanup = TRUE; break; } // Try to read more data from the local file if ((bytesWritten = fwrite(buffer, 1, bytesRead, ctx->fd)) <= 0) { res = GetLastError(); console_write_output( "\n" INBOUND_PREFIX " FS: fwrite failed, result %lu.\n", res); break; } textPrinted = FALSE; // Initialize the completion context for reading memset(&complete, 0, sizeof(complete)); complete.context = ctx; complete.routine.read = file_download_read_complete; // Read from the remote file res = channel_read(channel, remote, NULL, 0, 8192, &complete); } while (0); if (res != ERROR_SUCCESS) cleanup = TRUE; // If the clean up flag is set, close the channel and close the fd if (cleanup) { if (channel) channel_close(channel, remote, NULL, 0, NULL); // Free the context on error if (ctx->fd) fclose(ctx->fd); free(ctx); } // If text was displayed, show the console prompt if (textPrinted) console_write_prompt(); return res; }
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); }