mirror of
https://github.com/darlinghq/darling.git
synced 2024-11-23 12:19:43 +00:00
Temporarily revert 9980fa0a10
Turns out that it causes regressions for some users (see #1443). I'm going to move this change into a branch for testing and debugging and merge it back in once it's working reliably for everyone. This change isn't too important for most users of Darling; at the moment, the only significant thing it does is allow xcodebuild to work, but that's not essential at the moment.
This commit is contained in:
parent
141c24aaa8
commit
34351655a4
@ -3,9 +3,7 @@ project(shellspawn)
|
||||
add_definitions(-nostdinc)
|
||||
|
||||
add_darling_executable(shellspawn shellspawn.c duct_signals.c)
|
||||
add_darling_executable(shellsession shellsession.c)
|
||||
|
||||
install(TARGETS shellspawn shellsession DESTINATION libexec/darling/usr/libexec)
|
||||
install(FILES org.darlinghq.shellsession.plist DESTINATION libexec/darling/System/Library/LaunchDaemons)
|
||||
install(FILES org.darlinghq.shellspawn.plist DESTINATION libexec/darling/System/Library/LaunchAgents)
|
||||
install(TARGETS shellspawn DESTINATION libexec/darling/usr/libexec)
|
||||
install(FILES org.darlinghq.shellspawn.plist DESTINATION libexec/darling/System/Library/LaunchDaemons)
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>org.darlinghq.shellsession</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/libexec/shellsession</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -1,373 +0,0 @@
|
||||
/*
|
||||
* This file is part of Darling.
|
||||
*
|
||||
* Copyright (C) 2023 Darling Developers
|
||||
*
|
||||
* Darling is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Darling is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Darling. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syslimits.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <liblaunch/launch_priv.h>
|
||||
#include <bootstrap_priv.h>
|
||||
#include <vproc_priv.h>
|
||||
|
||||
#include "shellsession.h"
|
||||
#include "shellspawn.h"
|
||||
|
||||
#define MAX_ACCESS_TRIES 10
|
||||
|
||||
static void setup_socket_addr(struct sockaddr_un* addr);
|
||||
static void setup_session_socket_addr(unsigned int uid, struct sockaddr_un* addr);
|
||||
static int setup_socket(const struct sockaddr_un* addr);
|
||||
static void listen_for_connections(int server_socket);
|
||||
static void spawn_session(int sockfd);
|
||||
static void send_client_socket(int sockfd, int socket_to_send);
|
||||
static int try_connect_session(const struct sockaddr_un* addr);
|
||||
static void run_session_manager(unsigned int uid, unsigned int gid);
|
||||
|
||||
int main(int argc, const char* const* argv) {
|
||||
struct sockaddr_un server_addr;
|
||||
int server_socket = -1;
|
||||
|
||||
setup_socket_addr(&server_addr);
|
||||
|
||||
server_socket = setup_socket(&server_addr);
|
||||
if (server_socket < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
listen_for_connections(server_socket);
|
||||
|
||||
if (server_socket >= 0) {
|
||||
close(server_socket);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static void setup_socket_addr(struct sockaddr_un* addr) {
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sun_family = AF_UNIX;
|
||||
snprintf(addr->sun_path, sizeof(addr->sun_path), "%s", SHELLSESSION_SOCKPATH);
|
||||
};
|
||||
|
||||
static void setup_session_socket_addr(unsigned int uid, struct sockaddr_un* addr) {
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sun_family = AF_UNIX;
|
||||
snprintf(addr->sun_path, sizeof(addr->sun_path), "%s.%d", SHELLSPAWN_SOCKPATH, uid);
|
||||
};
|
||||
|
||||
static int setup_socket(const struct sockaddr_un* addr) {
|
||||
int server_socket = -1;
|
||||
|
||||
server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (server_socket == -1) {
|
||||
perror("Creating unix socket");
|
||||
goto err;
|
||||
}
|
||||
|
||||
fcntl(server_socket, F_SETFD, FD_CLOEXEC);
|
||||
unlink(addr->sun_path);
|
||||
|
||||
if (bind(server_socket, (struct sockaddr*)addr, sizeof(*addr)) == -1) {
|
||||
perror("Binding the unix socket");
|
||||
goto err;
|
||||
}
|
||||
|
||||
chmod(addr->sun_path, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (listen(server_socket, 1) == -1) {
|
||||
perror("Listening on unix socket");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return server_socket;
|
||||
|
||||
err:
|
||||
if (server_socket >= 0) {
|
||||
close(server_socket);
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
static void listen_for_connections(int server_socket) {
|
||||
int sock;
|
||||
struct sockaddr_un client_addr;
|
||||
socklen_t len = sizeof(client_addr);
|
||||
|
||||
while (true) {
|
||||
sock = accept(server_socket, (struct sockaddr*)&client_addr, &len);
|
||||
if (sock == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (fork() == 0) {
|
||||
// we don't need the server socket
|
||||
close(server_socket);
|
||||
server_socket = -1;
|
||||
|
||||
fcntl(sock, F_SETFD, FD_CLOEXEC);
|
||||
spawn_session(sock);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
close(sock);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void spawn_session(int sockfd) {
|
||||
shellsession_cmd_t cmd;
|
||||
struct sockaddr_un session_addr;
|
||||
int client_socket = -1;
|
||||
char session_started_path[PATH_MAX];
|
||||
int started_fd = -1;
|
||||
|
||||
if (read(sockfd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
setup_session_socket_addr(cmd.uid, &session_addr);
|
||||
snprintf(session_started_path, sizeof(session_started_path), "%s.%d", SHELLSESSION_STARTED_PATH, cmd.uid);
|
||||
|
||||
started_fd = open(session_started_path, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
|
||||
if (started_fd < 0 && errno == EEXIST) {
|
||||
// we already had a session set up; avoid setting up a new one.
|
||||
|
||||
// wait until shellspawn starts
|
||||
for (int i = 0; i < MAX_ACCESS_TRIES; i++) {
|
||||
if (access(session_addr.sun_path, F_OK) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
client_socket = try_connect_session(&session_addr);
|
||||
if (client_socket < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// now reply to the client with the session client socket
|
||||
send_client_socket(sockfd, client_socket);
|
||||
close(sockfd);
|
||||
return;
|
||||
} else if (started_fd < 0) {
|
||||
perror("Failed to create session indicator file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
// we didn't have a session set up already, so let's create one.
|
||||
|
||||
// we only need to create the session-running file; we don't need to write anything to it
|
||||
close(started_fd);
|
||||
|
||||
if (fork() == 0) {
|
||||
// this is the new session manager process
|
||||
close(sockfd);
|
||||
run_session_manager(cmd.uid, cmd.gid);
|
||||
} else {
|
||||
// wait until shellspawn starts
|
||||
for (int i = 0; i < MAX_ACCESS_TRIES; i++) {
|
||||
if (access(session_addr.sun_path, F_OK) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
client_socket = try_connect_session(&session_addr);
|
||||
if (client_socket < 0) {
|
||||
fprintf(stderr, "Error connecting to shellspawn session\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// now reply to the client with the session client socket
|
||||
send_client_socket(sockfd, client_socket);
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
close(sockfd);
|
||||
};
|
||||
|
||||
static void send_client_socket(int sockfd, int socket_to_send) {
|
||||
char dummy = '\0';
|
||||
struct msghdr msg;
|
||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||
struct cmsghdr *cmptr;
|
||||
struct iovec iov;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
|
||||
iov.iov_base = &dummy;
|
||||
iov.iov_len = sizeof(dummy);
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf);
|
||||
|
||||
cmptr = CMSG_FIRSTHDR(&msg);
|
||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmptr->cmsg_level = SOL_SOCKET;
|
||||
cmptr->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(cmptr), &socket_to_send, sizeof(socket_to_send));
|
||||
|
||||
if (sendmsg(sockfd, &msg, 0) != sizeof(dummy)) {
|
||||
fprintf(stderr, "Error sending reply: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
};
|
||||
|
||||
static int try_connect_session(const struct sockaddr_un* addr) {
|
||||
int client_socket = -1;
|
||||
|
||||
client_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (client_socket < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (connect(client_socket, (struct sockaddr*)addr, sizeof(*addr)) != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
return client_socket;
|
||||
|
||||
err:
|
||||
if (client_socket >= 0) {
|
||||
close(client_socket);
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
static void run_session_manager(unsigned int uid, unsigned int gid) {
|
||||
const char* login = NULL;
|
||||
struct passwd* pw = NULL;
|
||||
char* homedirTmp = NULL;
|
||||
mach_port_t subset = MACH_PORT_NULL;
|
||||
mach_port_t dummyService = MACH_PORT_NULL;
|
||||
kern_return_t kr = KERN_SUCCESS;
|
||||
|
||||
// we are the shellspawn instance for the user's session. this means we're in charge
|
||||
// of the user's session and are responsible for setting it up as macOS would.
|
||||
// we are essentially going to be doing the same kind of setup that LoginWindow
|
||||
// would do on macOS.
|
||||
|
||||
// switch ourselves to run under the user's UID and GID (but under Darling, this is all fake anyways)
|
||||
setgid(gid);
|
||||
setuid(uid);
|
||||
|
||||
// fix up env vars to what they should be
|
||||
pw = getpwuid(uid);
|
||||
if (pw != NULL)
|
||||
login = pw->pw_name;
|
||||
|
||||
if (!login)
|
||||
login = getlogin();
|
||||
|
||||
setenv("PATH", "/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin", 1);
|
||||
setenv("TMPDIR", "/private/tmp", 1);
|
||||
|
||||
asprintf(&homedirTmp, "HOME=/Users/%s", login);
|
||||
putenv(homedirTmp);
|
||||
homedirTmp = NULL; // `putenv()` assumes ownership of the string
|
||||
|
||||
//
|
||||
// IMPORTANT NOTE
|
||||
//
|
||||
// okay, so i have no clue how this whole session switching is supposed to work.
|
||||
// or rather, i do have *some* idea: we need to call `create_and_switch_to_per_session_launchd`
|
||||
// to switch to a per-user launchd (which will also trigger LaunchAgents for the user).
|
||||
// the problem is that the way this function works internally is that it calls `_vprocmgr_move_subset_to_user`.
|
||||
// this function, in turn, moves the current subset into the new per-user launchd session.
|
||||
// obviously, this means we must already have a subset prior to calling `create_and_switch_to_per_session_launchd`.
|
||||
//
|
||||
// the thing is, i can't see how (the modern version of) LoginWindow does this. maybe the API has changed since then
|
||||
// and it no longer moves a subset into the new session, but i can't see it creating a new subset at any point during
|
||||
// the session setup. but clearly, *we* need to do this, so let's go ahead and do so.
|
||||
//
|
||||
|
||||
if ((kr = bootstrap_subset(bootstrap_port, mach_task_self(), &subset)) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create bootstrap subset: %d\n", kr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// replace the bootstrap port with our subset port
|
||||
if ((kr = task_set_bootstrap_port(mach_task_self(), subset)) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Failed to replace bootstrap port: %d\n", kr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// we no longer need the old bootstrap port
|
||||
mach_port_deallocate(mach_task_self(), bootstrap_port);
|
||||
|
||||
bootstrap_port = subset;
|
||||
|
||||
//
|
||||
// ANOTHER IMPORTANT NOTE
|
||||
//
|
||||
// launchd requires the new subset to have at least one Mach service registered before switching to the per-user
|
||||
// session. to that end, we simply create a bogus service here.
|
||||
//
|
||||
if ((kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &dummyService)) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Failed to allocate dummy service port: %d\n", kr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((kr = mach_port_insert_right(mach_task_self(), dummyService, dummyService, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Failed to insert send right into dummy service port: %d\n", kr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((kr = bootstrap_register(bootstrap_port, "org.darlinghq.shellsession.dummy-service", dummyService)) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Failed to register dummy service: %d\n", kr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// set up a launchd session
|
||||
if (create_and_switch_to_per_session_launchd("shellspawn", LAUNCH_GLOBAL_ON_DEMAND) < 0) {
|
||||
fprintf(stderr, "Failed to set up launchd user session.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// unset the global-on-demand flag to kickstart jobs that need to run at load
|
||||
if (!_vproc_set_global_on_demand(false)) {
|
||||
fprintf(stderr, "Failed to unset global-on-demand flag.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// now we just need to stay alive for launchd to keep our session alive
|
||||
// (launchd will start shellspawn as a LaunchAgent, and that's what the `darling` command will actually send commands to)
|
||||
while (true) {
|
||||
pause();
|
||||
}
|
||||
};
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of Darling.
|
||||
*
|
||||
* Copyright (C) 2023 Darling Developers
|
||||
*
|
||||
* Darling is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Darling is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Darling. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SHELLSESSION_H_
|
||||
#define _SHELLSESSION_H_
|
||||
|
||||
#ifdef TESTING
|
||||
#define SHELLSESSION_SOCKPATH "/tmp/shellsession.sock"
|
||||
#define SHELLSESSION_STARTED_PATH "/tmp/shellsession.running"
|
||||
#else
|
||||
#define SHELLSESSION_SOCKPATH "/var/run/shellsession.sock"
|
||||
#define SHELLSESSION_STARTED_PATH "/var/run/shellsession.running"
|
||||
#endif
|
||||
|
||||
typedef struct shellsession_cmd {
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
} shellsession_cmd_t;
|
||||
|
||||
#endif // _SHELLSESSION_H_
|
||||
|
@ -64,10 +64,9 @@ void setupSocket(void)
|
||||
{
|
||||
struct sockaddr_un addr = {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = SHELLSPAWN_SOCKPATH
|
||||
};
|
||||
|
||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s.%d", SHELLSPAWN_SOCKPATH, getuid());
|
||||
|
||||
g_serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (g_serverSocket == -1)
|
||||
{
|
||||
@ -76,7 +75,7 @@ void setupSocket(void)
|
||||
}
|
||||
|
||||
fcntl(g_serverSocket, F_SETFD, FD_CLOEXEC);
|
||||
unlink(addr.sun_path);
|
||||
unlink(SHELLSPAWN_SOCKPATH);
|
||||
|
||||
if (bind(g_serverSocket, (struct sockaddr*) &addr, sizeof(addr)) == -1)
|
||||
{
|
||||
|
@ -37,7 +37,6 @@ along with Darling. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <pty.h>
|
||||
#include <pwd.h>
|
||||
#include "../shellspawn/shellspawn.h"
|
||||
#include "../shellspawn/shellsession.h"
|
||||
#include "darling.h"
|
||||
#include "darling-config.h"
|
||||
|
||||
@ -170,7 +169,7 @@ int main(int argc, char ** argv)
|
||||
{
|
||||
char socketPath[4096];
|
||||
|
||||
snprintf(socketPath, sizeof(socketPath), "%s" SHELLSESSION_SOCKPATH, prefix);
|
||||
snprintf(socketPath, sizeof(socketPath), "%s" SHELLSPAWN_SOCKPATH, prefix);
|
||||
|
||||
unlink(socketPath);
|
||||
|
||||
@ -546,20 +545,20 @@ static size_t escapeQuotes(char *dest, const char *src)
|
||||
return len;
|
||||
}
|
||||
|
||||
int connectToShellsession(void)
|
||||
int connectToShellspawn(void)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int sockfd;
|
||||
|
||||
// Connect to the shellsession daemon in the container
|
||||
// Connect to the shellspawn daemon in the container
|
||||
addr.sun_family = AF_UNIX;
|
||||
#if USE_LINUX_4_11_HACK
|
||||
addr.sun_path[0] = '\0';
|
||||
|
||||
strcpy(addr.sun_path, prefix);
|
||||
strcat(addr.sun_path, SHELLSESSION_SOCKPATH);
|
||||
strcat(addr.sun_path, SHELLSPAWN_SOCKPATH);
|
||||
#else
|
||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s" SHELLSESSION_SOCKPATH, prefix);
|
||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s" SHELLSPAWN_SOCKPATH, prefix);
|
||||
#endif
|
||||
|
||||
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
@ -578,66 +577,6 @@ int connectToShellsession(void)
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
static int startShellspawnSession(int sockfd)
|
||||
{
|
||||
shellsession_cmd_t cmd;
|
||||
|
||||
cmd.uid = g_originalGid;
|
||||
cmd.gid = g_originalGid;
|
||||
|
||||
if (write(sockfd, &cmd, sizeof(cmd)) != sizeof(cmd))
|
||||
{
|
||||
fprintf(stderr, "Error sending command to shellsession: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char dummy = '\0';
|
||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
struct cmsghdr *cmptr;
|
||||
int sessionFD;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf);
|
||||
|
||||
iov.iov_base = &dummy;
|
||||
iov.iov_len = sizeof(dummy);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
if (recvmsg(sockfd, &msg, 0) != sizeof(dummy))
|
||||
{
|
||||
fprintf(stderr, "Error receiving reply from shellsession: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cmptr = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
if (cmptr == NULL || cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != SCM_RIGHTS)
|
||||
{
|
||||
fprintf(stderr, "Invalid reply from shellsession: no attached FD\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (cmptr->cmsg_len != CMSG_LEN(sizeof(int)))
|
||||
{
|
||||
fprintf(stderr, "Invalid reply from shellsession: invalid CMSG length %lu (expected %lu)\n", cmptr->cmsg_len, sizeof(int));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memcpy(&sessionFD, CMSG_DATA(cmptr), sizeof(int));
|
||||
|
||||
if (sessionFD < 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid reply from shellsession: invalid FD %d\n", sessionFD);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return sessionFD;
|
||||
}
|
||||
|
||||
void setupShellspawnEnv(int sockfd)
|
||||
{
|
||||
static const char* skip_vars[] = {
|
||||
@ -763,8 +702,7 @@ void spawnShell(const char** argv)
|
||||
else
|
||||
buffer = NULL;
|
||||
|
||||
sockfd = connectToShellsession();
|
||||
sockfd = startShellspawnSession(sockfd);
|
||||
sockfd = connectToShellspawn();
|
||||
|
||||
setupShellspawnEnv(sockfd);
|
||||
|
||||
@ -788,9 +726,7 @@ void spawnBinary(const char* binary, const char** argv)
|
||||
int fds[3], master;
|
||||
int sockfd;
|
||||
|
||||
sockfd = connectToShellsession();
|
||||
sockfd = startShellspawnSession(sockfd);
|
||||
|
||||
sockfd = connectToShellspawn();
|
||||
setupShellspawnEnv(sockfd);
|
||||
|
||||
pushShellspawnCommand(sockfd, SHELLSPAWN_SETEXEC, binary);
|
||||
|
Loading…
Reference in New Issue
Block a user