Пример #1
0
static PyObject* is_fifo(PyObject *self, PyObject *args) {
        int r;
        int fd;
        const char *path = NULL;

#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
        if (!PyArg_ParseTuple(args, "i|O&:_is_fifo",
                              &fd, Unicode_FSConverter, &path))
                return NULL;
#else
        if (!PyArg_ParseTuple(args, "i|z:_is_fifo", &fd, &path))
                return NULL;
#endif

        r = sd_is_fifo(fd, path);
        if (set_error(r, path, NULL) < 0)
                return NULL;

        return PyBool_FromLong(r);
}
Пример #2
0
/**
 * Entry point into bt-daemon
 * @param argc Number of arguments passed
 * @param argv An array of string arguments
 * @returns EXIT_SUCCESS if the operation succeeded, otherwise EXIT_FAILURE
 */
int main(int argc, char *argv[])
{
	int fd;
	int smackfd = -1;
	socklen_t addr_len;
	struct sockaddr_un remote;
	int descriptors;
	int ret;
	bool manual_start = false;
	struct sigaction sa;

	if (!buxton_cache_smack_rules())
		exit(EXIT_FAILURE);
	smackfd = buxton_watch_smack_rules();
	if (smackfd < 0 && errno)
		exit(EXIT_FAILURE);

	self.nfds_alloc = 0;
	self.accepting_alloc = 0;
	self.nfds = 0;
	self.buxton.client.direct = true;
	self.buxton.client.uid = geteuid();
	if (!buxton_direct_open(&self.buxton))
		exit(EXIT_FAILURE);

	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sa.sa_handler = my_handler;
	ret = sigaction(SIGINT, &sa, NULL);
	if (ret == -1)
		exit(EXIT_FAILURE);
	ret = sigaction(SIGTERM, &sa, NULL);
	if (ret == -1)
		exit(EXIT_FAILURE);

	/* For client notifications */
	self.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
	/* Store a list of connected clients */
	LIST_HEAD_INIT(client_list_item, self.client_list);

	descriptors = sd_listen_fds(0);
	if (descriptors < 0) {
		buxton_log("sd_listen_fds: %m\n");
		exit(EXIT_FAILURE);
	} else if (descriptors == 0) {
		/* Manual invocation */
		manual_start = true;
		union {
			struct sockaddr sa;
			struct sockaddr_un un;
		} sa;

		fd = socket(AF_UNIX, SOCK_STREAM, 0);
		if (fd < 0) {
			buxton_log("socket(): %m\n");
			exit(EXIT_FAILURE);
		}

		memset(&sa, 0, sizeof(sa));
		sa.un.sun_family = AF_UNIX;
		strncpy(sa.un.sun_path, BUXTON_SOCKET, sizeof(sa.un.sun_path) - 1);
		sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0;

		ret = unlink(sa.un.sun_path);
		if (ret == -1 && errno != ENOENT) {
			exit(EXIT_FAILURE);
		}

		if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
			buxton_log("bind(): %m\n");
			exit(EXIT_FAILURE);
		}

		chmod(sa.un.sun_path, 0666);

		if (listen(fd, SOMAXCONN) < 0) {
			buxton_log("listen(): %m\n");
			exit(EXIT_FAILURE);
		}
		add_pollfd(&self, fd, POLLIN | POLLPRI, true);
	} else {
		/* systemd socket activation */
		for (fd = SD_LISTEN_FDS_START + 0; fd < SD_LISTEN_FDS_START + descriptors; fd++) {
			if (sd_is_fifo(fd, NULL)) {
				add_pollfd(&self, fd, POLLIN, false);
				buxton_debug("Added fd %d type FIFO\n", fd);
			} else if (sd_is_socket_unix(fd, SOCK_STREAM, -1, BUXTON_SOCKET, 0)) {
				add_pollfd(&self, fd, POLLIN | POLLPRI, true);
				buxton_debug("Added fd %d type UNIX\n", fd);
			} else if (sd_is_socket(fd, AF_UNSPEC, 0, -1)) {
				add_pollfd(&self, fd, POLLIN | POLLPRI, true);
				buxton_debug("Added fd %d type SOCKET\n", fd);
			}
		}
	}

	if (smackfd >= 0) {
		/* add Smack rule fd to pollfds */
		add_pollfd(&self, smackfd, POLLIN | POLLPRI, false);
	}

	buxton_log("%s: Started\n", argv[0]);

	/* Enter loop to accept clients */
	for (;;) {
		ret = poll(self.pollfds, self.nfds, -1);

		if (ret < 0) {
			buxton_log("poll(): %m\n");
			if (errno == EINTR) {
				if (do_shutdown)
					break;
				else
					continue;
			}
			break;
		}
		if (ret == 0)
			continue;

		for (nfds_t i=0; i<self.nfds; i++) {
			client_list_item *cl = NULL;
			char discard[256];

			if (self.pollfds[i].revents == 0)
				continue;

			if (self.pollfds[i].fd == -1) {
				/* TODO: Remove client from list  */
				buxton_debug("Removing / Closing client for fd %d\n", self.pollfds[i].fd);
				del_pollfd(&self, i);
				continue;
			}

			if (smackfd >= 0) {
				if (self.pollfds[i].fd == smackfd) {
					if (!buxton_cache_smack_rules())
						exit(EXIT_FAILURE);
					buxton_log("Reloaded Smack access rules\n");
					/* discard inotify data itself */
					while (read(smackfd, &discard, 256) == 256);
					continue;
				}
			}

			if (self.accepting[i] == true) {
				struct timeval tv;
				int fd;
				int on = 1;

				addr_len = sizeof(remote);

				if ((fd = accept(self.pollfds[i].fd,
				    (struct sockaddr *)&remote, &addr_len)) == -1) {
					buxton_log("accept(): %m\n");
					break;
				}

				buxton_debug("New client fd %d connected through fd %d\n", fd, self.pollfds[i].fd);

				cl = malloc0(sizeof(client_list_item));
				if (!cl)
					exit(EXIT_FAILURE);

				LIST_INIT(client_list_item, item, cl);

				cl->fd = fd;
				cl->cred = (struct ucred) {0, 0, 0};
				LIST_PREPEND(client_list_item, item, self.client_list, cl);

				/* poll for data on this new client as well */
				add_pollfd(&self, cl->fd, POLLIN | POLLPRI, false);

				/* Mark our packets as high prio */
				if (setsockopt(cl->fd, SOL_SOCKET, SO_PRIORITY, &on, sizeof(on)) == -1)
					buxton_log("setsockopt(SO_PRIORITY): %m\n");

				/* Set socket recv timeout */
				tv.tv_sec = SOCKET_TIMEOUT;
				tv.tv_usec = 0;
				if (setsockopt(cl->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
					       sizeof(struct timeval)) == -1)
					buxton_log("setsockopt(SO_RCVTIMEO): %m\n");

				/* check if this is optimal or not */
				break;
			}

			assert(self.accepting[i] == 0);
			if (smackfd >= 0)
				assert(self.pollfds[i].fd != smackfd);

			/* handle data on any connection */
			/* TODO: Replace with hash table lookup */
			LIST_FOREACH(item, cl, self.client_list)
				if (self.pollfds[i].fd == cl->fd)
					break;

			assert(cl);
			handle_client(&self, cl, i);
		}
	}

	buxton_log("%s: Closing all connections\n", argv[0]);

	if (manual_start)
		unlink(BUXTON_SOCKET);
	for (int i = 0; i < self.nfds; i++) {
		close(self.pollfds[i].fd);
	}
	for (client_list_item *i = self.client_list; i;) {
		client_list_item *j = i->item_next;
		free(i);
		i = j;
	}
	hashmap_free(self.notify_mapping);
	buxton_direct_close(&self.buxton);
	return EXIT_SUCCESS;
}
Пример #3
0
static int server_init(Server *s, unsigned n_sockets) {
        int r;
        unsigned i;

        assert(s);
        assert(n_sockets > 0);

        zero(*s);

        s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
        if (s->epoll_fd < 0) {
                r = log_error_errno(errno,
                                    "Failed to create epoll object: %m");
                goto fail;
        }

        for (i = 0; i < n_sockets; i++) {
                struct epoll_event ev;
                Fifo *f;
                int fd;

                fd = SD_LISTEN_FDS_START+i;

                r = sd_is_fifo(fd, NULL);
                if (r < 0) {
                        log_error_errno(r, "Failed to determine file descriptor type: %m");
                        goto fail;
                }

                if (!r) {
                        log_error("Wrong file descriptor type.");
                        r = -EINVAL;
                        goto fail;
                }

                f = new0(Fifo, 1);
                if (!f) {
                        r = -ENOMEM;
                        log_error_errno(errno, "Failed to create fifo object: %m");
                        goto fail;
                }

                f->fd = -1;

                zero(ev);
                ev.events = EPOLLIN;
                ev.data.ptr = f;
                if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
                        r = -errno;
                        fifo_free(f);
                        log_error_errno(errno, "Failed to add fifo fd to epoll object: %m");
                        goto fail;
                }

                f->fd = fd;
                LIST_PREPEND(fifo, s->fifos, f);
                f->server = s;
                s->n_fifos++;
        }

        r = bus_connect_system_systemd(&s->bus);
        if (r < 0) {
                log_error_errno(r, "Failed to get D-Bus connection: %m");
                r = -EIO;
                goto fail;
        }

        return 0;

fail:
        server_done(s);

        return r;
}