Пример #1
0
Файл: io.c Проект: yarec/s48
static s48_ref_t
posix_pipe(s48_call_t call)
{  int 		fildes[2],
    		status;
  s48_ref_t	in_channel, out_channel;
  s48_ref_t 	id = s48_enter_string_latin_1_2 (call, "pipe");

  RETRY_OR_RAISE_NEG(status, pipe(fildes));

  in_channel = s48_add_channel_2(call, s48_channel_status_input_2(call), id, fildes[0]);

  if (!s48_channel_p_2(call, in_channel)) {
    ps_close_fd(fildes[0]);		/* retries if interrupted */
    ps_close_fd(fildes[1]);		/* retries if interrupted */
    s48_raise_scheme_exception_2(call, s48_extract_long_2(call, in_channel), 0); }

  RETRY_OR_RAISE_NEG(status, fcntl(fildes[1], F_SETFL, O_NONBLOCK));
  out_channel = s48_add_channel_2(call, s48_channel_status_output_2(call), id, fildes[1]);

  if (!s48_channel_p_2(call, out_channel)) {
    s48_close_channel(fildes[0]);
    ps_close_fd(fildes[1]);		/* retries if interrupted */
    s48_raise_scheme_exception_2(call, s48_extract_long_2(call, in_channel), 0); }

  return s48_cons_2(call, in_channel, out_channel);
}
Пример #2
0
static s48_value
s48_socket(s48_value server_p)
{
  int		fd,
    		mode;
  s48_value	channel;

  fd = socket(AF_INET, SOCK_STREAM, 0);

  if (fd < 0)
    s48_raise_os_error(errno);

  if (-1 == fcntl(fd, F_SETFL, O_NONBLOCK))
    s48_raise_os_error(errno);

  mode = (server_p == S48_FALSE) ?
    S48_CHANNEL_STATUS_SPECIAL_OUTPUT :
    S48_CHANNEL_STATUS_SPECIAL_INPUT;

  channel = s48_add_channel(mode, s48_enter_string("socket"), fd);

  if (!S48_CHANNEL_P(channel)) {
    ps_close_fd(fd);		/* retries if interrupted */
    s48_raise_scheme_exception(s48_extract_fixnum(channel), 0); };

  return channel;
}
Пример #3
0
Файл: io.c Проект: yarec/s48
static s48_ref_t
posix_dup(s48_call_t call, s48_ref_t channel, s48_ref_t new_mode)
{
  int		new_fd, old_fd, flags;
  long          status;
  s48_ref_t	s48_status;
  s48_ref_t	old_mode;
  s48_ref_t 	new_channel;

  if (!s48_channel_p_2(call, channel) ||
      s48_eq_p_2(call, s48_channel_status_2(call, channel), s48_channel_status_closed_2(call)))
    s48_assertion_violation_2(call, "posix_dup", "not an open channel", 1, channel);
  
  old_fd = s48_unsafe_extract_long_2(call, s48_unsafe_channel_os_index_2(call, channel));
  old_mode = s48_unsafe_channel_status_2(call, channel);

  RETRY_OR_RAISE_NEG(new_fd, dup(old_fd));
  
  s48_status = s48_set_channel_os_index_2(call, channel, new_fd);

  if (!s48_true_p_2(call, s48_status)) {
    ps_close_fd(new_fd);		/* retries if interrupted */
    s48_raise_scheme_exception_2(call, s48_extract_long_2(call, s48_status), 1, channel); }

  if (s48_eq_p_2(call, new_mode, s48_channel_status_output_2(call))
      && s48_eq_p_2(call, old_mode, s48_channel_status_input_2(call))) {
    RETRY_OR_RAISE_NEG(flags, fcntl(new_fd, F_GETFL));
    RETRY_OR_RAISE_NEG(status, fcntl(new_fd, F_SETFL, flags | O_NONBLOCK)); }

  new_channel = s48_add_channel_2(call,
				  s48_false_p_2(call, new_mode) ? old_mode : new_mode,
				  s48_unsafe_channel_id_2(call, channel),
				  old_fd);

  if (!s48_channel_p_2(call, new_channel)) {
    ps_close_fd(old_fd);		/* retries if interrupted */
    s48_raise_scheme_exception_2(call, s48_extract_long_2(call, new_channel), 1, channel); }

  return new_channel;
}
Пример #4
0
Файл: io.c Проект: yarec/s48
static s48_ref_t
posix_dup2(s48_call_t call, s48_ref_t channel, s48_ref_t new_fd)
{
  s48_ref_t 	new_channel;
  s48_ref_t	s48_status;
  int 		status;
  int 		new_c_fd, old_c_fd;

  if (!s48_channel_p_2(call, channel) ||
      s48_eq_p_2(call, s48_channel_status_2(call, channel), s48_channel_status_closed_2(call)))
    s48_assertion_violation_2(call, "posix_dup2", "not an open channel", 1, channel);

  if (!s48_fixnum_p_2(call, new_fd) || new_fd < 0)
    s48_assertion_violation_2(call, "posix_dup2", "fd not a nonnegative fixnum", 1, new_fd);

  old_c_fd = s48_extract_long_2(call, s48_unsafe_channel_os_index_2(call, channel));
  new_c_fd = s48_extract_long_2(call, new_fd);

  s48_close_channel(new_c_fd);

  RETRY_OR_RAISE_NEG(status, dup2(old_c_fd, new_c_fd));

  s48_status = s48_set_channel_os_index_2(call, channel, new_c_fd);

  if (!s48_true_p_2(call, s48_status)) {
    ps_close_fd(new_c_fd);		/* retries if interrupted */
    s48_raise_scheme_exception_2(call, s48_extract_long_2(call, s48_status), 1, channel); }

  new_channel = s48_add_channel_2(call,
				  s48_unsafe_channel_status_2(call, channel),
				  s48_unsafe_channel_id_2(call, channel),
				  old_c_fd);

  if (!s48_channel_p_2(call, new_channel)) {
    ps_close_fd(old_c_fd);		/* retries if interrupted */
    s48_raise_scheme_exception_2(call, s48_extract_long_2(call, new_channel), 1, channel); }

  return new_channel;
}
Пример #5
0
static s48_value
s48_connect(s48_value channel, s48_value machine, s48_value port)
{
  int			socket_fd,
			output_fd,
    			port_number;
  char			*machine_name;
  struct hostent	*host;
  struct sockaddr_in	address;
  s48_value		output_channel;

  S48_CHECK_CHANNEL(channel);
  socket_fd = S48_UNSAFE_EXTRACT_FIXNUM(S48_UNSAFE_CHANNEL_OS_INDEX(channel));

  S48_CHECK_STRING(machine);
  machine_name = S48_UNSAFE_EXTRACT_STRING(machine);
  
  S48_CHECK_FIXNUM(port);
  port_number = S48_UNSAFE_EXTRACT_FIXNUM(port);
  
  /*
   * Get the host and initialize `address'.
   */

  host = gethostbyname(machine_name);
  if (host == NULL)
    s48_raise_os_error(errno);
  
  memset((void *)&address, 0, sizeof(address));
  address.sin_family = host->h_addrtype;

  if (host->h_length > sizeof(address.sin_addr))
    s48_raise_range_error(s48_enter_fixnum(host->h_length),
			  S48_UNSAFE_ENTER_FIXNUM(0),
			  s48_enter_fixnum(sizeof(address.sin_addr)));
  memcpy((void *)&address.sin_addr, (void *)host->h_addr, host->h_length);
  address.sin_port = htons(port_number);

  /*
   * Try the connection.  If it works we make an output channel and return it.
   * The original socket channel will be used as the input channel.
   */

  if (connect(socket_fd, (struct sockaddr *)&address, sizeof(address)) >= 0) {
    S48_STOB_SET(channel, S48_CHANNEL_STATUS_OFFSET, S48_CHANNEL_STATUS_INPUT);
    
    output_fd = dup(socket_fd);
    
    if (output_fd == -1)
      s48_raise_os_error(errno);
    
    output_channel = s48_add_channel(S48_CHANNEL_STATUS_OUTPUT,
				     s48_enter_string("socket connection"),
				     output_fd);
    
    if (!S48_CHANNEL_P(output_channel)) {
      ps_close_fd(output_fd);		/* retries if interrupted */
      s48_raise_scheme_exception(s48_extract_fixnum(output_channel), 0); };
    
    return output_channel;
  }

  /*
   * Check for errors.  If we need to retry we mark the socket as pending
   * and return #F to tell the Scheme procedure to wait.
   */

  /* already connected, will raise an error from Scheme */
  if (errno == EISCONN)
    return S48_TRUE;

  if (errno != EWOULDBLOCK && errno != EINTR && errno != EALREADY
      && errno != EINPROGRESS && errno != EAGAIN)
    s48_raise_os_error(errno);

  if (! (s48_add_pending_fd(socket_fd, FALSE)))
    s48_raise_out_of_memory_error();

  return S48_FALSE;
}
Пример #6
0
static s48_value
s48_accept(s48_value channel)
{
  int			socket_fd,
   			connect_fd,
			output_fd,
			len;
  struct sockaddr_in	address;
  s48_value		input_channel,
			output_channel;

  S48_CHECK_CHANNEL(channel);
  socket_fd = S48_UNSAFE_EXTRACT_FIXNUM(S48_UNSAFE_CHANNEL_OS_INDEX(channel));

  len = sizeof(address);
  connect_fd = accept(socket_fd, (struct sockaddr *)&address, &len);
  
  /*
   * Check for a connection.  If we have one we create two channels, one
   * input and one, with a dup()'ed fd, output.  Lots of error checking
   * makes this messy.
   */

  if (connect_fd >= 0) {
    
    S48_DECLARE_GC_PROTECT(1);
  
    if (-1 == fcntl(connect_fd, F_SETFL, O_NONBLOCK))
      s48_raise_os_error(errno);

    input_channel = s48_add_channel(S48_CHANNEL_STATUS_INPUT,
				    s48_enter_string("socket connection"),
				    connect_fd);

    if (!S48_CHANNEL_P(input_channel)) {
      ps_close_fd(connect_fd);		/* retries if interrupted */
      s48_raise_scheme_exception(s48_extract_fixnum(input_channel), 0); };
    
    output_fd = dup(connect_fd);

    if (output_fd == -1)
      s48_raise_os_error(errno);

    S48_GC_PROTECT_1(input_channel);
  
    output_channel = s48_add_channel(S48_CHANNEL_STATUS_OUTPUT,
				     s48_enter_string("socket connection"),
				     output_fd);
    
    if (!S48_CHANNEL_P(output_channel)) {
      /* input_channel will eventually be closed by the GC */
      ps_close_fd(output_fd);		/* retries if interrupted */
      s48_raise_scheme_exception(s48_extract_fixnum(output_channel), 0); };
    
    S48_GC_UNPROTECT();

    return s48_cons(input_channel, output_channel);
  }

  /*
   * Check for errors.  If we need to retry we mark the socket as pending
   * and return #F to tell the Scheme procedure to wait.
   */

  if ((errno != EWOULDBLOCK) && (errno != EINTR) && (errno != EAGAIN))
    s48_raise_os_error(errno);

  if (! s48_add_pending_fd(socket_fd, TRUE))
    s48_raise_out_of_memory_error();

  return S48_FALSE;
}