Exemple #1
0
int
twopence_sock_recv_buffer(twopence_sock_t *sock, twopence_buf_t *bp)
{
	unsigned int count;
	int n;

	count = twopence_buf_tailroom(bp);
	if (count == 0) {
		twopence_debug("%s: no tailroom in buffer", __func__);
		errno = ENOBUFS;
		return -1;
	}

#if 0
	/* Testing: simulate serial pipe behavior - large packets get chopped
	 * up into 4k chunks */
	if (count > 4096)
		count = 4096;
#endif

	n = read(sock->fd, twopence_buf_tail(bp), count);
	if (n > 0)
		twopence_buf_advance_tail(bp, n);
	else if (n < 0)
		twopence_debug("%s: recv() returns error: %m", __func__);
	return n;
}
Exemple #2
0
void
twopence_sock_free(twopence_sock_t *sock)
{
	twopence_debug("%s(%d)\n", __func__, sock->fd);
	if (sock->closeit && sock->fd >= 0)
		close(sock->fd);

	twopence_queue_destroy(&sock->xmit_queue);
	if (sock->recv_buf)
		twopence_buf_free(sock->recv_buf);
	free(sock);
}
Exemple #3
0
/*
 * Sockets in listen mode.
 */
int
server_listen_doio(twopence_conn_pool_t *poll, twopence_conn_t *conn)
{
	twopence_sock_t *sock;

	sock = twopence_conn_accept(conn);
	if (sock != NULL) {
		twopence_conn_t *new_conn = server_new_connection(sock, &server_ops);

		twopence_debug("Accepted incoming connection");
		twopence_conn_set_keepalive(new_conn, -1);
		twopence_conn_pool_add_connection(poll, new_conn);
	}
	return 0;
}
Exemple #4
0
bool
server_run_command_send(twopence_transaction_t *trans)
{
	twopence_trans_channel_t *channel;
	int status;
	pid_t pid;
	bool pending_output;

	pending_output = false;
	if ((channel = twopence_transaction_find_source(trans, TWOPENCE_STDOUT)) != NULL
	 && !twopence_transaction_channel_is_read_eof(channel))
		pending_output = true;
	if ((channel = twopence_transaction_find_source(trans, TWOPENCE_STDERR)) != NULL
	 && !twopence_transaction_channel_is_read_eof(channel))
		pending_output = true;

	if (trans->pid) {
		pid = waitpid(trans->pid, &status, WNOHANG);
		if (pid > 0) {
			twopence_debug("%s: process exited, status=%u\n", twopence_transaction_describe(trans), status);
			twopence_transaction_close_sink(trans, 0);
			trans->status = status;
			trans->pid = 0;
		}
	}

	if (!trans->done && trans->pid == 0 && !pending_output) {
		int st = trans->status;

		if (WIFEXITED(st)) {
			twopence_transaction_send_major(trans, 0);
			twopence_transaction_send_minor(trans, WEXITSTATUS(st));
		} else
		if (WIFSIGNALED(st)) {
			if (WTERMSIG(st) == SIGALRM) {
				twopence_transaction_send_timeout(trans);
			} else {
				twopence_transaction_fail2(trans, EFAULT, WTERMSIG(st));
			}
		} else {
			twopence_transaction_fail2(trans, EFAULT, 2);
		}
		trans->done = true;
	}

	return true;
}
Exemple #5
0
static bool
server_change_to_home(const struct passwd *user)
{
	const char *homedir;

	if ((homedir = user->pw_dir) == NULL || homedir[0] != '/') {
		twopence_debug("user %s has a home directory of \"%s\", substituting \"/\"",
				user->pw_name, user->pw_dir);
		homedir = "/";
	}

	if (chdir(homedir) < 0) {
		twopence_log_error("Cannot change to user %s's home directory: chdir(%s) failed: %m",
				user->pw_name, user->pw_dir);
		return false;
	}

	return true;
}
Exemple #6
0
/*
 * Open the TCP socket
 *
 * Returns the file descriptor if successful, or -1 if failed
 */
static twopence_sock_t *
__twopence_tcp_open(struct twopence_pipe_target *pipe_handle)
{
  struct twopence_tcp_target *handle = (struct twopence_tcp_target *) pipe_handle;
  char *copy, *hostname, *portname = NULL;
  struct addrinfo hints;
  struct addrinfo *ai_list, *ai;
  int socket_fd = -1;
  int res;

  copy = hostname = twopence_strdup(handle->server_spec);
  if (hostname[0] == '[') {
    /* Something like [::1] */
    char *s;

    for (s = ++hostname; *s != ']'; ++s) {
      if (*s == '\0') {
        twopence_log_error("tcp: cannot parse \"%s\"", handle->server_spec);
	free(copy);
        return NULL;
      }
    }
    *s++ = '\0';
    if (*s == ':')
      portname = ++s;
    /* Any other garbage is silently ignored for now */
  } else
  if ((portname = strchr(hostname, ':')) != NULL)
    *portname++ = '\0';

  if (portname == NULL)
    portname = TWOPENCE_TCP_PORT_DEFAULT_STR;

  memset(&hints, 0, sizeof(hints));
  hints.ai_socktype = SOCK_STREAM;
  res = getaddrinfo(hostname, portname, &hints, &ai_list);

  free(copy);
  copy = hostname = portname = NULL;

  if (res != 0) {
    twopence_log_error("tcp: cannot resolve \"%s\": %s", handle->server_spec, gai_strerror(res));
    return NULL;
  }

  twopence_debug("trying to open connection to %s", handle->server_spec);
  for (ai = ai_list; ai && socket_fd < 0; ai = ai->ai_next) {
    socket_fd = socket(ai->ai_family, SOCK_STREAM, 0);
    if (socket_fd <= 0)
      break;

    // Open the connection
    if (connect(socket_fd, ai->ai_addr, ai->ai_addrlen) < 0) {
      /* Okay, this address didn't work. Try the next one */
      close(socket_fd);
      socket_fd = -1;
    }
  }

  freeaddrinfo(ai_list);
  if (socket_fd <= 0)
    return NULL;

  /* Note, we do not pass O_NONBLOCK here, but we do set O_CLOEXEC */
  return twopence_sock_new_flags(socket_fd, O_RDWR | O_CLOEXEC);
}
Exemple #7
0
int
server_open_file_as(const char *username, const char *filename, unsigned int filemode, int oflags, int *status)
{
	struct stat stb;
	struct saved_ids saved_ids;
	struct passwd *user;
	int fd;

	if (!(user = server_get_user(username, status))) {
		twopence_debug("Unknown user \"%s\"\n", username);
		return -1;
	}

	/* If the path is not absolute, interpret it relatively to the
	 * user's home directory */
	if (filename[0] != '/') {
		filename = server_build_path(user->pw_dir, filename);
		if (filename == NULL) {
			twopence_log_error("Unable to build path from user %s's home \"%s\" and relative name \"%s\"\n",
					username, user->pw_dir, filename);
			*status = ENAMETOOLONG;
			return false;
		}
	}

	twopence_debug("%s(user=%s, file=%s, flags=0%0)\n", __func__, username, filename, oflags);

	/* We may want to have the client specify the file mode as well */
	if (!strcmp(username, "root")) {
		fd = open(filename, oflags, filemode);
		if (fd < 0)
			*status = errno;
	} else {
		if (!server_change_hats_temporarily(user, &saved_ids, status))
			return -1;
		fd = open(filename, oflags, filemode);
		if (fd < 0)
			*status = errno;

		server_restore_privileges(&saved_ids);
	}

	if (fd < 0)
		return -1;

	if (fstat(fd, &stb) < 0) {
		*status = errno;
		twopence_log_error("failed to stat \"%s\": %m", filename);
		close(fd);
		return -1;
	}
	if (!S_ISREG(stb.st_mode)) {
		twopence_log_error("%s: not a regular file\n", filename);
		*status = EISDIR;
		close(fd);
		return -1;
	}
	if (oflags != O_RDONLY && fchmod(fd, filemode) < 0) {
		*status = errno;
		twopence_log_error("failed to change file mode \"%s\" to 0%o: %m", filename, filemode);
		close(fd);
		return -1;
	}

	return fd;
}