Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
0
/** @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;
}
Пример #4
0
/** @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;
}
Пример #5
0
/** @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;
}
Пример #6
0
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
}
Пример #7
0
    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");
}
Пример #8
0
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;
}
Пример #9
0
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 */
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
/*
 * 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;
}
Пример #13
0
/*
 * 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;
}
Пример #14
0
/**
 * @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;
}
Пример #15
0
/** @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;
}
Пример #16
0
/**
 * @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;
}
Пример #17
0
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);
}
Пример #18
0
/**
 * @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;
}
Пример #19
0
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 */
Пример #20
0
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);

	}
}
Пример #21
0
/**
 * 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;
}
Пример #22
0
/*
 * 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;
}
Пример #23
0
/*
 * 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;
}
Пример #24
0
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);
}