mirror of
https://github.com/systemd/systemd
synced 2024-10-01 22:05:33 +00:00
varlink: add helper that adds a connection via stdio to a varlink server
This adds varlink_server_add_connection_stdio() as wrapper around varlink_server_add_connection_pair(), that steals stdin/stdout fds and turns them into a varlink connection. To be safe it replaces stdin/stdout with /dev/null fds.
This commit is contained in:
parent
e73ae07b52
commit
4120151f7b
|
@ -3703,6 +3703,66 @@ int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
int varlink_server_add_connection_stdio(VarlinkServer *s, Varlink **ret) {
|
||||
_cleanup_close_ int input_fd = -EBADF, output_fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
|
||||
input_fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 3);
|
||||
if (input_fd < 0)
|
||||
return -errno;
|
||||
|
||||
output_fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 3);
|
||||
if (output_fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = rearrange_stdio(-EBADF, -EBADF, STDERR_FILENO);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fd_nonblock(input_fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fd_nonblock(output_fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
struct stat input_st;
|
||||
if (fstat(input_fd, &input_st) < 0)
|
||||
return -errno;
|
||||
|
||||
struct stat output_st;
|
||||
if (fstat(output_fd, &output_st) < 0)
|
||||
return -errno;
|
||||
|
||||
/* If stdin/stdout are both pipes and have the same owning uid/gid then let's synthesize a "struct
|
||||
* ucred" from the owning UID/GID, since we got them passed in with such ownership. We'll not fill in
|
||||
* the PID however, since there's no way to know which process created a pipe. */
|
||||
struct ucred ucred, *pucred;
|
||||
if (S_ISFIFO(input_st.st_mode) &&
|
||||
S_ISFIFO(output_st.st_mode) &&
|
||||
input_st.st_uid == output_st.st_uid &&
|
||||
input_st.st_gid == output_st.st_gid) {
|
||||
ucred = (struct ucred) {
|
||||
.uid = input_st.st_uid,
|
||||
.gid = input_st.st_gid,
|
||||
};
|
||||
pucred = &ucred;
|
||||
} else
|
||||
pucred = NULL;
|
||||
|
||||
r = varlink_server_add_connection_pair(s, input_fd, output_fd, pucred, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_FD(input_fd);
|
||||
TAKE_FD(output_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varlink_server_listen_auto(VarlinkServer *s) {
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
int r, n = 0;
|
||||
|
|
|
@ -222,6 +222,7 @@ int varlink_server_listen_fd(VarlinkServer *s, int fd);
|
|||
int varlink_server_listen_auto(VarlinkServer *s);
|
||||
int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
|
||||
int varlink_server_add_connection_pair(VarlinkServer *s, int input_fd, int output_fd, const struct ucred *ucred_override, Varlink **ret);
|
||||
int varlink_server_add_connection_stdio(VarlinkServer *s, Varlink **ret);
|
||||
|
||||
/* Bind callbacks */
|
||||
int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);
|
||||
|
|
Loading…
Reference in a new issue